莫方教程网

专业程序员编程教程与实战案例分享

MFC转QT:Qt基础知识



1. Qt框架概述

Qt的历史和版本

Qt是一个跨平台的C++应用程序开发框架,由挪威公司Trolltech(现为Qt Company)于1991年创建。Qt的发展历程:

  • 1991年:Qt项目启动
  • 1995年:Qt 1.0发布,首个商业版本
  • 1999年:Qt 2.0发布,引入Qt Designer
  • 2005年:Nokia收购Trolltech
  • 2008年:Qt 4.4首次以开源和商业双许可证发布
  • 2011年:Digia收购Qt
  • 2014年:Qt 5.0发布,引入Qt Quick和QML
  • 2020年:Qt 6.0发布,带来现代C++特性支持和性能改进

当前Qt分为两种许可证:

  • 商业许可证:适用于开发商业闭源软件
  • 开源许可证:遵循LGPL/GPL协议,适用于开源软件开发

Qt vs MFC的主要区别

特性

Qt

MFC

平台支持

跨平台(Windows, macOS, Linux, Android, iOS)

仅Windows

开发理念

信号槽机制,事件驱动

消息映射,基于Windows消息

界面开发

支持可视化设计和代码编写,布局管理灵活

基于对话框资源,布局较为固定

内存管理

父子对象树自动管理,支持智能指针

需手动管理内存,容易泄漏

国际化

内置国际化支持

需额外工作实现国际化

绘图系统

统一抽象API (QPainter)

依赖Windows GDI/GDI+

开发效率

代码量少,API设计现代化

代码量大,API设计较旧

扩展性

可通过插件和扩展机制丰富功能

扩展能力有限

文档质量

详尽的文档和示例

文档相对简单

对MFC开发者而言,Qt的优势:

  1. 跨平台能力,一套代码可运行在多个操作系统
  2. 更现代化的API设计,减少代码量
  3. 对C++11/14/17/20特性支持更好
  4. 信号槽机制比消息映射更直观
  5. 布局系统可实现响应式界面
  6. 更丰富的控件集,不依赖Windows原生控件
  7. 更好的自动内存管理机制

Qt Creator IDE的使用

Qt Creator是Qt框架的官方集成开发环境,功能强大且针对Qt开发优化。与Visual Studio(MFC常用IDE)相比:

主要功能

  • 代码编辑器(支持代码高亮、自动完成、语法检查)
  • 集成Qt Designer(可视化UI设计工具)
  • 集成Qt Assistant(帮助文档)
  • 版本控制集成(Git、SVN等)
  • 图形化调试器
  • 性能分析工具
  • 跨平台编译与部署工具

界面布局

  1. 欢迎模式:快速访问最近项目、教程和示例
  2. 编辑模式:编写代码
  3. 设计模式:使用Qt Designer设计UI
  4. 调试模式:调试应用程序
  5. 项目模式:管理项目文件和配置

项目创建与管理

  1. File → New Project(新建项目)
  2. 选择项目模板(如Qt Widgets Application)
  3. 配置项目设置(名称、位置、构建系统)
  4. 选择所需Qt模块
  5. 选择构建套件(编译器、Qt版本)

编译与运行

  • 点击左下角的运行按钮或按Ctrl+R
  • 可选择不同的构建配置(Debug/Release)
  • 可配置命令行参数和运行环境

调试技巧

  • 设置断点:点击代码行号旁或按F9
  • 单步执行:F10(不进入函数)或F11(进入函数)
  • 观察变量:调试时可在右侧面板查看变量值
  • 使用qDebug()函数输出调试信息

对于从MFC迁移的开发者来说,Qt Creator提供了更集成和统一的开发体验,不需要像Visual Studio那样安装额外的扩展。

2. Qt项目结构

项目文件(.pro)

Qt项目文件(.pro)是Qt工程的核心配置文件,类似于MFC在Visual Studio中的.vcxproj文件,但语法更简洁。

.pro文件的基本结构

 # 指定使用的Qt模块
 QT += core gui widgets network
 
 # 启用C++11标准
 CONFIG += c++11
 
 # 定义目标名称
 TARGET = MyApplication
 # 指定应用程序类型(app, lib)
 TEMPLATE = app
 
 # 源文件列表
 SOURCES += \
     main.cpp \
     mainwindow.cpp \
     dialog.cpp
 
 # 头文件列表
 HEADERS += \
     mainwindow.h \
     dialog.h
 
 # UI文件列表
 FORMS += \
     mainwindow.ui \
     dialog.ui
 
 # 资源文件
 RESOURCES += \
     resources.qrc
 
 # 附加包含路径
 INCLUDEPATH += \
     $PWD/thirdparty/include
 
 # 链接库
 LIBS += \
     -L$PWD/thirdparty/lib -lsome_library
 
 # 条件编译
 win32 {
     # Windows平台特定设置
     RC_ICONS = app_icon.ico
 }
 macx {
     # macOS平台特定设置
     ICON = app_icon.icns
 }

.pro文件与MFC项目配置的主要区别

  1. 语法更简洁,不像Visual Studio的XML格式那么冗长
  2. 直接支持跨平台条件配置
  3. 模块化设计,可以轻松添加或移除功能模块
  4. 可以使用变量和函数简化配置

QMake vs CMake: Qt还支持使用CMake构建系统,Qt 6更推荐使用CMake。CMake提供更强大的跨平台构建能力,但学习曲线较陡。

资源文件(.qrc)

Qt资源系统允许将应用程序资源(图像、文本文件等)编译到可执行文件中,而MFC通常使用.rc资源文件和资源编辑器。

.qrc文件的XML结构

 <!DOCTYPE RCC>
 <RCC version="1.0">
     <qresource prefix="/images">
         <file>icons/open.png</file>
         <file>icons/save.png</file>
         <file>icons/exit.png</file>
     </qresource>
     <qresource prefix="/translations">
         <file>app_zh.qm</file>
         <file>app_en.qm</file>
     </qresource>
 </RCC>

资源访问方式

 // 加载图标
 QIcon icon(":/images/icons/open.png");
 // 读取文本文件
 QFile file(":/texts/readme.txt");

Qt资源系统的优势

  1. 资源嵌入可执行文件,不需要单独分发
  2. 使用统一的命名空间访问,简化代码
  3. 支持压缩减小体积
  4. 不需要处理Windows资源ID

信号与槽机制(对比MFC消息映射)

信号与槽是Qt最独特和强大的特性之一,它提供了一种类型安全的对象间通信机制,远比MFC的消息映射系统更灵活和直观。

基本概念

  • 信号(Signal):当某个事件发生时由对象发出
  • 槽(Slot):响应信号的函数
  • 连接(Connection):将信号和槽关联起来

对比MFC消息映射

特性

Qt信号槽

MFC消息映射

类型安全

编译时检查参数类型

运行时处理,无类型检查

灵活性

任何对象间可建立连接

主要用于窗口消息处理

实现方式

基于元对象系统

基于宏和消息表

代码可读性

直观表达对象间关系

消息映射表与处理函数分离

参数传递

可传递任意类型和数量的参数

受限于Windows消息结构

多对多关系

一信号可连接多槽,一槽可响应多信号

一消息对应一处理函数

信号槽示例

 // MFC按钮点击处理
 // 在消息映射中:
 BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
     ON_BN_CLICKED(IDC_BUTTON1, &CMyDialog::OnButton1Clicked)
 END_MESSAGE_MAP()
 
 // 处理函数
 void CMyDialog::OnButton1Clicked()
 {
     // 处理逻辑
 }
 
 // Qt按钮点击处理
 // 在构造函数中:
 connect(ui->pushButton, &QPushButton::clicked, this, &MyDialog::onButton1Clicked);
 
 // 槽函数
 void MyDialog::onButton1Clicked()
 {
     // 处理逻辑
 }

Qt 5引入的新连接语法

 // Qt 4语法(基于字符串)
 connect(sender, SIGNAL(valueChanged(int)), receiver, SLOT(updateValue(int)));
 
 // Qt 5语法(基于函数指针,更安全)
 connect(sender, &Sender::valueChanged, receiver, &Receiver::updateValue);
 
 // Lambda表达式连接
 connect(sender, &Sender::valueChanged, [=](int value) {
     // 处理逻辑
 });

信号槽的优势

  1. 解耦发送者和接收者,实现松散耦合
  2. 编译时类型检查减少错误
  3. 自动处理对象生命周期(当对象销毁时自动断开连接)
  4. 可以跨线程通信(使用Qt::QueuedConnection)

MOC(Meta-Object Compiler)原理

MOC是Qt元对象系统的核心组件,为C++添加反射、内省等能力,这是标准C++不直接支持的功能。MOC是Qt区别于MFC的核心技术之一。

工作原理

  1. 处理包含Q_OBJECT宏的头文件
  2. 生成包含元对象信息的C++源文件(moc_*.cpp)
  3. 这些生成的文件与普通源文件一起编译链接

元对象系统提供的能力

  • 信号与槽机制
  • 运行时类型信息(RTTI)
  • 动态属性系统
  • 国际化支持

Q_OBJECT宏的作用

 class MyClass : public QObject
 {
     Q_OBJECT  // 启用元对象特性
     
     // 声明属性
     Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
     
 public:
     QString name() const { return m_name; }
     void setName(const QString &name) {
         if (m_name != name) {
             m_name = name;
             emit nameChanged(name);
         }
     }
     
 signals:
     void nameChanged(const QString &name);
     
 private:
     QString m_name;
 };

对MFC开发者的价值

  1. 简化组件间通信,不再需要复杂的消息传递
  2. 提供运行时反射能力,可以在运行时查询对象属性和方法
  3. 支持属性系统,自动处理通知和绑定
  4. 为Qt其他高级特性(如属性动画、模型/视图架构)提供基础

MOC处理是自动化的,开发者通常不需要手动干预,Qt构建系统会自动调用MOC并将生成的文件纳入编译过程。

3. Qt模块系统

Qt采用模块化设计,将功能分为多个模块,开发者可以根据需要选择使用。这与MFC的单一整体库结构有很大不同。

QtCore - 核心非GUI功能

QtCore是Qt的基础模块,提供核心的非GUI功能。所有Qt应用程序都会使用此模块。

主要功能

  • 对象系统:QObject基类、信号槽、属性系统
  • 容器类:QString, QList, QVector, QMap等
  • 线程支持:QThread, QMutex, QWaitCondition等
  • I/O操作:QFile, QIODevice, QTextStream等
  • 日期时间:QDate, QTime, QDateTime
  • 正则表达式:QRegularExpression
  • XML处理:QXmlStreamReader, QXmlStreamWriter
  • JSON处理:QJsonDocument, QJsonObject
  • 插件系统:QPluginLoader
  • 事件系统:QEvent, QCoreApplication

相比MFC的优势

  1. 更现代化的容器类,直接支持迭代器和算法
  2. 统一的字符串处理(支持Unicode)
  3. 更完善的线程同步原语
  4. 更简洁的文件和I/O操作API
  5. 跨平台一致性,不依赖Windows API

代码示例

 // 文件操作
 QFile file("data.txt");
 if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
     QTextStream in(&file);
     QString line = in.readLine();
     // 处理文本...
 }
 
 // 容器和算法
 QList<int> numbers = {1, 2, 3, 4, 5};
 std::sort(numbers.begin(), numbers.end(), std::greater<int>());
 
 // 日期时间处理
 QDateTime now = QDateTime::currentDateTime();
 QString formattedDate = now.toString("yyyy-MM-dd hh:mm:ss");
 
 // JSON处理
 QJsonObject json;
 json["name"] = "John";
 json["age"] = 30;
 QJsonDocument doc(json);
 QString jsonString = doc.toJson(QJsonDocument::Compact);

QtGui - 基本GUI功能

QtGui模块提供图形用户界面(GUI)组件的基本类。这个模块处理窗口系统集成、事件处理、OpenGL和2D图形等。

主要功能

  • 窗口系统集成:QWindow, QScreen
  • 绘图:QPainter, QPen, QBrush, QPainterPath
  • 图像处理:QImage, QPixmap, QBitmap
  • 字体和文本:QFont, QFontMetrics
  • 颜色处理:QColor, QColorSpace
  • 图形项:QIcon, QCursor
  • OpenGL支持:QOpenGLContext, QOpenGLFunctions
  • 事件基类:QKeyEvent, QMouseEvent, QPaintEvent等

与MFC绘图系统对比

功能

Qt (QPainter)

MFC (CDC)

坐标系统

逻辑坐标,支持变换

设备和逻辑坐标,映射模式

绘图原语

直观的图形API

基于Windows GDI函数

渲染质量

支持抗锯齿,高质量渲染

依赖GDI/GDI+能力

平台一致性

所有平台一致的外观

主要针对Windows

打印支持

统一的打印接口

需要特殊处理打印DC

代码示例

 // Qt绘图
 void MyWidget::paintEvent(QPaintEvent *) {
     QPainter painter(this);
     
     // 启用抗锯齿
     painter.setRenderHint(QPainter::Antialiasing);
     
     // 绘制线条
     painter.setPen(QPen(Qt::blue, 2));
     painter.drawLine(10, 10, 100, 100);
     
     // 绘制矩形
     painter.setBrush(QBrush(Qt::red));
     painter.drawRect(120, 10, 80, 80);
     
     // 绘制文本
     painter.setPen(Qt::black);
     painter.setFont(QFont("Arial", 12));
     painter.drawText(50, 150, "Hello Qt!");
 }
 
 // 图像处理
 QImage image("photo.jpg");
 QImage scaled = image.scaled(200, 150, Qt::KeepAspectRatio);

QtWidgets - 经典桌面风格UI组件

QtWidgets模块提供一套传统的桌面风格的UI控件,类似于MFC的控件集,但更丰富和现代化。

主要组件

  • 应用程序窗口:QMainWindow, QDialog, QWidget
  • 布局管理器:QBoxLayout, QGridLayout, QFormLayout
  • 按钮:QPushButton, QCheckBox, QRadioButton
  • 输入控件:QLineEdit, QTextEdit, QSpinBox, QComboBox
  • 显示控件:QLabel, QProgressBar
  • 容器控件:QTabWidget, QStackedWidget, QGroupBox
  • 项视图控件:QListView, QTreeView, QTableView
  • 模型类:QStringListModel, QStandardItemModel
  • 菜单和工具栏:QMenuBar, QMenu, QToolBar, QAction
  • 对话框:QMessageBox, QFileDialog, QColorDialog

与MFC控件对比

MFC控件

Qt等效控件

Qt优势

CButton

QPushButton, QCheckBox, QRadioButton

更明确的类型区分

CEdit

QLineEdit, QTextEdit

内置验证器和自动完成

CListCtrl

QListView, QTableView

模型/视图分离,更易定制

CTreeCtrl

QTreeView

模型/视图分离,更易定制

CComboBox

QComboBox

更现代的API和样式

CListBox

QListWidget

项目可包含富文本和图标

CStatic

QLabel

支持富文本和图像

CTabCtrl

QTabWidget

更简洁的API

CToolBar

QToolBar

支持拖放和自定义

CMenu

QMenu

支持图标和快捷键

CRichEditCtrl

QTextEdit

内置HTML支持

代码示例

// 创建主窗口
QMainWindow mainWindow;
mainWindow.setWindowTitle("Qt Widget示例");
mainWindow.resize(800, 600);

// 创建中央控件
QWidget *centralWidget = new QWidget(&mainWindow);
mainWindow.setCentralWidget(centralWidget);

// 创建布局
QVBoxLayout *layout = new QVBoxLayout(centralWidget);

// 添加标签
QLabel *label = new QLabel("请输入名字:", centralWidget);
layout->addWidget(label);

// 添加输入框
QLineEdit *lineEdit = new QLineEdit(centralWidget);
layout->addWidget(lineEdit);

// 添加按钮
QPushButton *button = new QPushButton("确定", centralWidget);
layout->addWidget(button);

// 连接信号槽
QObject::connect(button, &QPushButton::clicked, [=]() {
    QString name = lineEdit->text();
    QMessageBox::information(&mainWindow, "欢迎", "你好, " + name + "!");
});

// 显示窗口
mainWindow.show();

QtNetwork - 网络编程

QtNetwork模块提供跨平台的网络编程API,支持TCP/IP、HTTP、FTP等协议。相比MFC使用WinSock或WinInet的封装,Qt的网络模块更加易用且跨平台。

主要功能

  • TCP套接字:QTcpSocket, QTcpServer
  • UDP套接字:QUdpSocket
  • SSL/TLS支持:QSslSocket
  • HTTP客户端:QNetworkAccessManager, QNetworkRequest, QNetworkReply
  • DNS查询:QDnsLookup
  • 主机信息:QHostInfo, QHostAddress
  • 网络代理支持:QNetworkProxy
  • WebSocket支持:QWebSocket, QWebSocketServer

相比MFC网络编程的优势

  1. 更简洁的API,减少样板代码
  2. 基于信号槽的异步处理,避免回调地狱
  3. 内置SSL/TLS支持,不需额外库
  4. 高级HTTP客户端功能(如cookie, 认证, 重定向)

代码示例

// HTTP请求
QNetworkAccessManager manager;
QNetworkRequest request(QUrl("https://api.example.com/data"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

QNetworkReply *reply = manager.get(request);

// 使用信号槽处理响应
QObject::connect(reply, &QNetworkReply::finished, [=]() {
    if (reply->error() == QNetworkReply::NoError) {
        QByteArray data = reply->readAll();
        // 处理数据...
    } else {
        qDebug() << "Error:" << reply->errorString();
    }
    reply->deleteLater();
});

// TCP客户端
QTcpSocket socket;
socket.connectToHost("example.com", 12345);

// 连接建立事件
QObject::connect(&socket, &QTcpSocket::connected, [&]() {
    socket.write("Hello Server");
});

// 数据接收事件
QObject::connect(&socket, &QTcpSocket::readyRead, [&]() {
    QByteArray data = socket.readAll();
    // 处理接收数据...
});

QtSql - 数据库操作

QtSql模块提供数据库集成,支持多种数据库引擎,包括SQLite、MySQL、PostgreSQL、Oracle和Microsoft SQL Server等。相比MFC中使用ODBC、DAO或ADO,Qt的数据库API更加统一和面向对象。

主要功能

  • 数据库连接:QSqlDatabase
  • SQL查询:QSqlQuery
  • 结果集处理:QSqlRecord, QSqlField
  • 数据库模型:QSqlQueryModel, QSqlTableModel, QSqlRelationalTableModel
  • 数据库事务:QSqlDriver
  • 错误处理:QSqlError
  • 数据库信息:QSqlDatabase::tables(), QSqlDatabase::drivers()

相比MFC数据库编程的优势

  1. 统一API接口,不同数据库引擎代码相似
  2. 与模型/视图架构无缝集成
  3. 内置SQLite支持,无需额外依赖
  4. 自动类型转换和参数绑定

代码示例

// 建立数据库连接
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("mydata.db");

if (!db.open()) {
    qDebug() << "Error: " << db.lastError().text();
    return;
}

// 执行查询
QSqlQuery query;
query.prepare("SELECT id, name, age FROM users WHERE age > ?");
query.addBindValue(18);

if (query.exec()) {
    while (query.next()) {
        int id = query.value(0).toInt();
        QString name = query.value(1).toString();
        int age = query.value(2).toInt();
        
        qDebug() << "User:" << id << name << age;
    }
}

// 使用SqlTableModel与视图绑定
QSqlTableModel model;
model.setTable("users");
model.setEditStrategy(QSqlTableModel::OnManualSubmit);
model.select();

// 设置列标题
model.setHeaderData(0, Qt::Horizontal, "ID");
model.setHeaderData(1, Qt::Horizontal, "姓名");
model.setHeaderData(2, Qt::Horizontal, "年龄");

// 与表格视图绑定
QTableView *view = new QTableView();
view->setModel(&model);
view->show();

// 事务处理
db.transaction();
QSqlQuery insertQuery;
insertQuery.prepare("INSERT INTO users (name, age) VALUES (?, ?)");
insertQuery.addBindValue("张三");
insertQuery.addBindValue(25);

if (insertQuery.exec()) {
    db.commit();
} else {
    db.rollback();
}

Qt的数据库模块还提供了关系型表格模型,可以轻松处理表间关系,这是MFC所不具备的强大功能:

 // 关系型表格模型
 QSqlRelationalTableModel model;
 model.setTable("orders");
 model.setRelation(1, QSqlRelation("customers", "id", "name"));
 model.setRelation(2, QSqlRelation("products", "id", "description"));
 model.select();
 
 // 自动显示关联表的数据
 QTableView *view = new QTableView();
 view->setModel(&model);
 view->setItemDelegate(new QSqlRelationalDelegate(view));
 view->show();



控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言

    滇ICP备2024046894号-1