Qt 框架采用模块化架构,核心模块包括 Qt Core
(基础功能)、Qt Widgets
(桌面 UI 组件)、Qt Gui
(图形相关),扩展模块涵盖网络、数据库、多线程、Qt Quick 等。所有类均以 Q
为前缀(如 QObject
、QWidget
),无统一命名空间,但通过模块划分功能边界。
一、核心基础模块(Qt Core)
Qt Core 是 Qt 框架的基础,提供跨平台的核心功能,不依赖图形界面,适用于控制台程序和服务端开发。
1. QCoreApplication
应用程序核心类
作为非 GUI 应用的入口点,管理应用程序的生命周期、事件循环和全局资源,GUI 应用的 QApplication
继承自此类。
-
核心函数:
static QCoreApplication* instance()
:返回应用程序实例(单例模式)。int exec()
:启动事件循环(程序运行的核心,处理事件队列,直至quit()
被调用)。void quit()
:终止事件循环(使exec()
返回 0)。void exit(int returnCode)
:终止事件循环并指定返回码(常用于主窗口关闭时)。QString applicationName()
/void setApplicationName(const QString& name)
:获取/设置应用名称(用于窗口标题、日志等)。QString applicationVersion()
/void setApplicationVersion(const QString& version)
:获取/设置应用版本。
-
使用场景 :所有 Qt 程序必须创建
QCoreApplication
或其派生类实例,是事件循环的起点。 -
示例代码:
cpp#include <QCoreApplication> #include <QDebug> int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); // 初始化应用 app.setApplicationName("MyConsoleApp"); app.setApplicationVersion("1.0.0"); qDebug() << "Application started. Press Ctrl+C to exit."; return app.exec(); // 启动事件循环 }
2. QObject
元对象基类
Qt 中几乎所有类的基类,提供信号与槽 、事件处理 、对象树管理 、元对象信息等核心功能,是 Qt 框架的灵魂。
-
核心特性与函数:
-
对象树与内存管理:
void setParent(QObject* parent)
:设置父对象,子对象生命周期依赖于父对象(父对象销毁时自动删除子对象)。QObject* parent() const
:获取父对象。QList<QObject*> children() const
:获取所有子对象。void deleteLater()
:延迟删除对象(确保当前事件处理完成后再销毁,避免野指针)。
-
元对象系统:
const QMetaObject* metaObject() const
:返回元对象(存储类的元信息,如信号、槽、属性)。bool inherits(const char* className)
:判断是否继承自指定类(如obj->inherits("QWidget")
)。QString objectName() const
/void setObjectName(const QString& name)
:获取/设置对象名称(用于查找对象findChild()
)。
-
信号与槽相关:
bool connect(const QObject* sender, const char* signal, const QObject* receiver, const char* slot, Qt::ConnectionType type = Qt::AutoConnection)
:连接信号与槽(Qt 4 风格)。bool disconnect(const QObject* sender, const char* signal, const QObject* receiver, const char* slot)
:断开连接。
-
事件处理:
bool event(QEvent* e)
:事件处理入口(可重写以自定义事件逻辑)。bool eventFilter(QObject* watched, QEvent* event)
:事件过滤器(拦截其他对象的事件)。
-
-
使用场景 :所有需要信号与槽、事件处理或对象树管理的类都应继承
QObject
,并在类声明中添加Q_OBJECT
宏(启用元对象功能)。 -
示例代码:
cpp#include <QObject> #include <QDebug> class MyObject : public QObject { Q_OBJECT // 必须添加,启用元对象功能 public: explicit MyObject(QObject* parent = nullptr) : QObject(parent) {} signals: void valueChanged(int newValue); // 信号(仅声明,无需实现) public slots: void onValueChanged(int value) { // 槽函数 qDebug() << "Value changed to:" << value; } }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); MyObject obj1, obj2; // 连接信号与槽:obj1的valueChanged触发obj2的onValueChanged QObject::connect(&obj1, &MyObject::valueChanged, &obj2, &MyObject::onValueChanged); emit obj1.valueChanged(42); // 发射信号,槽函数会被调用 return app.exec(); } #include "main.moc" // 若使用qmake,需包含moc生成文件
3. QString
字符串类
Qt 中的字符串处理类,基于 Unicode,支持动态长度、自动内存管理,提供丰富的字符串操作接口,优于 C++ 标准库的 std::string
。
-
核心函数:
-
构造与转换:
QString(const char* str)
:从 C 字符串构造(自动转换为 Unicode)。QString::fromUtf8(const char* str)
:从 UTF-8 编码构造。const char* toUtf8() const
:转换为 UTF-8 编码的 C 字符串(返回QByteArray
)。int toInt(bool* ok = nullptr, int base = 10) const
:转换为整数。double toDouble(bool* ok = nullptr) const
:转换为浮点数。
-
字符串操作:
QString append(const QString& str)
/QString operator+(const QString& str)
:拼接字符串。QString replace(int position, int n, const QString& after)
:替换子串。QString mid(int position, int n = -1) const
:提取子串(从 position 开始,长度 n,默认到结尾)。int indexOf(const QString& str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
:查找子串位置。bool contains(const QString& str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
:判断是否包含子串。QString toLower() const
/QString toUpper() const
:转换为小写/大写。
-
其他常用方法:
int length() const
/bool isEmpty() const
:获取长度/判断为空。QString trimmed() const
:去除首尾空白字符。static QString number(int n, int base = 10)
:将数字转换为字符串。
-
-
使用场景 :所有字符串处理场景(UI 文本、文件路径、网络数据等),避免直接使用
char*
或std::string
以减少编码问题。 -
示例代码:
cpp#include <QString> #include <QDebug> int main() { QString str = "Hello, Qt!"; qDebug() << "Length:" << str.length(); // 输出 9 QString upper = str.toUpper(); qDebug() << upper; // 输出 "HELLO, QT!" if (str.contains("Qt", Qt::CaseInsensitive)) { qDebug() << "Contains 'Qt'"; } QString numStr = QString::number(123.45, 'f', 1); // 格式化为保留1位小数 qDebug() << numStr; // 输出 "123.5" return 0; }
4. 容器类(QList
、QVector
、QMap
等)
Qt 提供一系列模板容器类,替代 C++ 标准容器,优化了跨平台性能和 Qt 特性集成(如与 QVariant
兼容)。
-
QList<T>
:最常用的动态数组,内部实现为数组+链表混合结构,支持快速随机访问和中间插入。-
核心函数:
append()
、prepend()
、insert()
、removeAt()
、at()
、count()
、isEmpty()
、contains()
。 -
示例:
cppQList<int> numbers; numbers << 1 << 2 << 3; // 插入元素 numbers.append(4); qDebug() << numbers.at(2); // 输出 3 numbers.removeAt(0); // 移除第一个元素
-
-
QVector<T>
:连续内存的动态数组,类似std::vector
,适合频繁随机访问。- 核心函数:
resize()
、data()
(返回原始指针)、operator[]
、fill()
。
- 核心函数:
-
QMap<Key, T>
:有序键值对容器(基于红黑树),按键排序,支持范围查询。-
核心函数:
insert(key, value)
、value(key, defaultValue)
、contains(key)
、remove(key)
、keys()
、values()
。 -
示例:
cppQMap<QString, int> scores; scores["Alice"] = 90; scores.insert("Bob", 85); qDebug() << scores["Alice"]; // 输出 90 if (scores.contains("Bob")) { qDebug() << "Bob's score:" << scores.value("Bob"); }
-
-
QHash<Key, T>
:无序哈希表,查找速度快于QMap
(平均 O(1)),但不保证顺序。
5. QVariant
变体类型
用于存储任意 Qt 数据类型(如 int
、QString
、QList
等),支持类型转换,常用于需要动态类型的场景(如 QSettings
、模型视图框架)。
-
核心函数:
QVariant(Type type)
:构造指定类型的变体。void setValue(const T& value)
:设置值(自动推断类型)。T value<T>() const
:获取值(若类型不匹配返回默认值)。bool canConvert(Type type) const
:判断是否可转换为指定类型。bool convert(Type type)
:转换为指定类型(成功返回 true)。
-
示例代码:
cpp#include <QVariant> #include <QDebug> int main() { QVariant var(42); // 存储整数 qDebug() << var.typeName(); // 输出 "int" qDebug() << var.toInt(); // 输出 42 var.setValue(QString("Hello")); // 存储字符串 qDebug() << var.toString(); // 输出 "Hello" if (var.canConvert<int>()) { qDebug() << "Can convert to int:" << var.toInt(); // 转换失败,返回0 } return 0; }
6. QTimer
定时器类
用于触发定时事件,支持单次触发和周期性触发,基于 Qt 事件循环,精度适中(毫秒级)。
-
核心函数:
void start(int msec)
:启动定时器(每隔 msec 毫秒触发一次)。void singleShot(int msec, const QObject* receiver, const char* member)
:静态方法,单次触发(msec 后调用槽函数)。void setInterval(int msec)
:设置间隔时间。void stop()
:停止定时器。- 信号:
timeout()
(定时器触发时发射)。
-
示例代码:
cpp#include <QCoreApplication> #include <QTimer> #include <QDebug> class TimerExample : public QObject { Q_OBJECT public: TimerExample(QObject* parent = nullptr) : QObject(parent) { // 创建周期性定时器 auto timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &TimerExample::onTimeout); timer->start(1000); // 每秒触发一次 } public slots: void onTimeout() { qDebug() << "Timer triggered"; } }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); TimerExample example; // 单次定时器:3秒后退出应用 QTimer::singleShot(3000, &app, &QCoreApplication::quit); return app.exec(); } #include "main.moc"
二、Qt Widgets 模块(桌面 UI 组件)
Qt Widgets 提供用于构建桌面应用的 UI 组件,基于 QWidget
类,支持传统的窗口、按钮、文本框等控件,是 Qt 最成熟的 UI 解决方案。
1. QApplication
应用程序类
继承自 QCoreApplication
,用于管理 GUI 应用的资源、窗口和事件(如鼠标、键盘事件),是所有 Widgets 应用的入口。
-
核心函数:
static QApplication* instance()
:返回应用实例。int exec()
:启动 GUI 事件循环(处理用户输入、窗口刷新等)。static QWidget* activeWindow()
:获取当前活跃窗口。static void setStyle(const QString& style)
:设置应用样式(如 "Fusion"、"Windows"、"Macintosh")。static QPalette palette()
/void setPalette(const QPalette& palette)
:获取/设置全局调色板。
-
示例代码:
cpp#include <QApplication> #include <QWidget> int main(int argc, char *argv[]) { QApplication app(argc, argv); app.setApplicationName("MyFirstGUI"); app.setStyle("Fusion"); // 使用跨平台的Fusion样式 QWidget window; // 创建主窗口 window.setWindowTitle("Hello Qt Widgets"); window.resize(400, 300); // 设置窗口大小 window.show(); // 显示窗口 return app.exec(); // 启动事件循环 }
2. QWidget
基础窗口部件类
所有 UI 控件的基类,可作为独立窗口或其他控件的子部件,提供窗口属性(大小、位置、标题)和事件处理。
-
核心属性与函数:
-
窗口状态:
void show()
/void hide()
:显示/隐藏部件。void setWindowTitle(const QString& title)
:设置窗口标题(仅顶级窗口有效)。void resize(int w, int h)
/void setGeometry(int x, int y, int w, int h)
:设置大小/位置和大小。QSize sizeHint() const
:返回推荐大小(布局管理器会参考此值)。
-
样式与外观:
void setStyleSheet(const QString& styleSheet)
:设置 CSS 风格的样式表(如setStyleSheet("background-color: red;")
)。void setEnabled(bool enabled)
:设置是否启用(禁用时控件灰显,不响应事件)。
-
布局管理:
void setLayout(QLayout* layout)
:为部件设置布局管理器(自动管理子部件位置)。
-
-
示例代码:
cpp#include <QApplication> #include <QWidget> #include <QPushButton> int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; window.setWindowTitle("QWidget Example"); window.setGeometry(100, 100, 300, 200); // 位置(100,100),大小300x200 // 创建按钮作为窗口的子部件 QPushButton button("Click Me", &window); button.setGeometry(100, 80, 100, 30); // 相对于父窗口的位置和大小 window.show(); return app.exec(); }
3. 常用控件类
QPushButton
按钮控件
用于触发操作的按钮,支持文本、图标,发射 clicked()
信号。
- 核心函数:
QPushButton(const QString& text, QWidget* parent = nullptr)
:构造带文本的按钮。void setIcon(const QIcon& icon)
:设置图标。- 信号:
clicked(bool checked = false)
(点击时发射)、pressed()
(按下时)、released()
(释放时)。
QLineEdit
单行文本框
用于输入或显示单行文本,支持密码模式、输入限制等。
- 核心函数:
QString text() const
/void setText(const QString& text)
:获取/设置文本。void setEchoMode(QLineEdit::EchoMode mode)
:设置回显模式(Normal
正常显示,Password
显示掩码)。void setReadOnly(bool readOnly)
:设置为只读。- 信号:
textChanged(const QString& text)
(文本变化时)、returnPressed()
(按下回车时)。
QTextEdit
多行文本框
支持富文本编辑,可输入多行文本、插入图片等。
- 核心函数:
QString toPlainText() const
/void setPlainText(const QString& text)
:获取/设置纯文本。void setHtml(const QString& html)
:设置 HTML 格式文本。void append(const QString& text)
:追加文本。
QComboBox
下拉列表
提供可选列表,支持单选,可编辑。
- 核心函数:
void addItem(const QString& text)
/void addItems(const QStringList& list)
:添加选项。int currentIndex() const
/void setCurrentIndex(int index)
:获取/设置当前选中索引。QString currentText() const
:获取当前选中文本。- 信号:
currentIndexChanged(int index)
、currentTextChanged(const QString& text)
。
QCheckBox
复选框
支持勾选/取消勾选的复选框,可用于多选场景。
- 核心函数:
bool isChecked() const
/void setChecked(bool checked)
:获取/设置勾选状态。- 信号:
toggled(bool checked)
(状态变化时)。
QRadioButton
单选按钮
用于互斥选择(同一父部件或同一 QButtonGroup
中只能选中一个)。
- 核心函数:
-
与
QCheckBox
类似,信号toggled(bool checked)
。 -
需配合
QButtonGroup
实现互斥:cppQButtonGroup* group = new QButtonGroup(parent); group->addButton(radio1, 0); // 关联按钮和ID group->addButton(radio2, 1);
-
4. 布局管理器(QLayout
派生类)
自动管理子部件的位置和大小,适应窗口尺寸变化,避免硬编码坐标。
QVBoxLayout
垂直布局
按垂直方向排列部件,从上到下依次放置。
QHBoxLayout
水平布局
按水平方向排列部件,从左到右依次放置。
QGridLayout
网格布局
按行列网格排列部件,支持跨行列。
核心函数(通用):
-
void addWidget(QWidget* widget, int stretch = 0, Qt::Alignment alignment = Qt::Alignment())
:添加部件。 -
void addLayout(QLayout* layout, int stretch = 0)
:嵌套布局。 -
void setSpacing(int spacing)
:设置部件间距。 -
void setContentsMargins(int left, int top, int right, int bottom)
:设置布局边缘留白。 -
示例代码:
cpp#include <QApplication> #include <QWidget> #include <QVBoxLayout> #include <QHBoxLayout> #include <QPushButton> #include <QLineEdit> int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; window.setWindowTitle("Layout Example"); // 创建垂直布局作为主布局 QVBoxLayout* mainLayout = new QVBoxLayout(&window); // 添加文本框 QLineEdit* edit = new QLineEdit(); mainLayout->addWidget(edit); // 创建水平布局放置按钮 QHBoxLayout* buttonLayout = new QHBoxLayout(); buttonLayout->addWidget(new QPushButton("OK")); buttonLayout->addWidget(new QPushButton("Cancel")); // 将水平布局添加到主布局 mainLayout->addLayout(buttonLayout); // 设置布局间距和边距 mainLayout->setSpacing(10); mainLayout->setContentsMargins(20, 20, 20, 20); window.resize(300, 150); window.show(); return app.exec(); }
5. QMainWindow
主窗口类
提供标准主窗口结构:标题栏、菜单栏、工具栏、状态栏和中央部件,适合构建复杂应用。
-
核心函数:
void setCentralWidget(QWidget* widget)
:设置中央部件(主窗口必须有中央部件)。QMenuBar* menuBar()
:获取菜单栏(自动创建)。QToolBar* addToolBar(const QString& title)
:添加工具栏。QStatusBar* statusBar()
:获取状态栏(自动创建)。
-
示例代码:
cpp#include <QApplication> #include <QMainWindow> #include <QMenu> #include <QAction> #include <QTextEdit> int main(int argc, char *argv[]) { QApplication app(argc, argv); QMainWindow mainWin; mainWin.setWindowTitle("QMainWindow Example"); mainWin.resize(800, 600); // 设置中央部件(文本编辑区) QTextEdit* centralWidget = new QTextEdit(); mainWin.setCentralWidget(centralWidget); // 创建菜单栏和菜单 QMenu* fileMenu = mainWin.menuBar()->addMenu("File"); // 添加菜单项 QAction* newAction = fileMenu->addAction("New"); QAction* openAction = fileMenu->addAction("Open"); fileMenu->addSeparator(); // 添加分隔线 QAction* exitAction = fileMenu->addAction("Exit"); // 连接退出动作到主窗口关闭 QObject::connect(exitAction, &QAction::triggered, &mainWin, &QMainWindow::close); // 添加状态栏提示 newAction->setStatusTip("Create a new document"); mainWin.statusBar()->showMessage("Ready"); mainWin.show(); return app.exec(); }
6. QDialog
对话框类
用于短期交互(如输入参数、显示消息),模态(阻塞父窗口)或非模态(不阻塞)。
-
核心函数:
int exec()
:以模态方式显示(返回结果码,如QDialog::Accepted
)。void show()
:以非模态方式显示。void accept()
/void reject()
:关闭对话框并返回对应结果码。
-
标准对话框:
QMessageBox
:消息框(提示、警告、错误、询问),静态方法如QMessageBox::information()
、QMessageBox::question()
。QFileDialog
:文件选择对话框,QFileDialog::getOpenFileName()
获取打开文件路径。QInputDialog
:输入对话框,QInputDialog::getText()
获取用户输入文本。
-
示例代码:
cpp#include <QApplication> #include <QMainWindow> #include <QPushButton> #include <QMessageBox> #include <QFileDialog> int main(int argc, char *argv[]) { QApplication app(argc, argv); QMainWindow mainWin; // 添加按钮触发对话框 QPushButton* msgBtn = new QPushButton("Show Message"); mainWin.setCentralWidget(msgBtn); // 连接按钮点击到消息框 QObject::connect(msgBtn, &QPushButton::clicked, [&]() { // 显示询问对话框 int result = QMessageBox::question(&mainWin, "Question", "Do you want to open a file?", QMessageBox::Yes | QMessageBox::No); if (result == QMessageBox::Yes) { // 显示文件选择对话框 QString filePath = QFileDialog::getOpenFileName(&mainWin, "Open File", "/home", "Text Files (*.txt)"); if (!filePath.isEmpty()) { QMessageBox::information(&mainWin, "Selected File", "You selected: " + filePath); } } }); mainWin.show(); return app.exec(); }
三、信号与槽机制(Qt 核心特性)
信号与槽(Signals & Slots)是 Qt 用于对象间通信的机制,替代传统回调,支持类型安全和松散耦合。
1. 基本概念
- 信号(Signal):对象状态变化时发射的通知(如按钮被点击、文本框内容变化),仅声明,无需实现。
- 槽(Slot):接收信号并处理的函数(可像普通函数一样调用),需实现。
- 连接(Connection) :通过
QObject::connect()
将信号与槽绑定,信号发射时槽函数自动执行。
2. 连接方式
Qt 支持多种连接类型(Qt::ConnectionType
),决定槽函数的执行线程和时机:
连接类型 | 说明 |
---|---|
Qt::AutoConnection |
自动选择(默认):同线程用直接连接,跨线程用队列连接 |
Qt::DirectConnection |
直接调用:槽函数在发射信号的线程执行(同步,可能阻塞信号发射线程) |
Qt::QueuedConnection |
队列调度:槽函数在接收者线程的事件循环中执行(异步,线程安全) |
Qt::BlockingQueuedConnection |
阻塞队列:同队列连接,但信号发射线程会阻塞至槽函数执行完毕(跨线程) |
-
示例代码 :
cpp// Qt 5+ 新语法(类型安全,推荐) connect(sender, &Sender::signalName, receiver, &Receiver::slotName, Qt::QueuedConnection); // Qt 4 旧语法(字符串匹配,不推荐) connect(sender, SIGNAL(signalName(int)), receiver, SLOT(slotName(int)), Qt::DirectConnection);
3. 信号与槽的要求
- 信号和槽的参数类型必须兼容(槽的参数可少于信号,多余参数被忽略)。
- 信号必须声明在类的
signals
区域(无需public
/private
修饰,默认为public
)。 - 槽可声明在
public slots
、protected slots
或private slots
区域,行为类似对应访问权限的函数。 - 继承
QObject
并添加Q_OBJECT
宏的类才能使用信号与槽(需通过 moc 工具预处理)。
4. 高级用法
-
lambda 表达式作为槽:简化短逻辑处理(Qt 5.0+ 支持):
cppconnect(button, &QPushButton::clicked, [this]() { qDebug() << "Button clicked, count:" << ++m_count; });
-
信号连接信号:一个信号发射时触发另一个信号:
cppconnect(obj1, &MyObject::valueChanged, obj2, &MyObject::valueChanged);
-
断开连接:不再需要时断开,避免悬空指针:
cppdisconnect(sender, &Sender::signalName, receiver, &Receiver::slotName);
四、事件处理机制
Qt 事件处理负责响应用户输入(鼠标、键盘)、系统通知(窗口大小变化、定时器)等,通过事件对象(QEvent
)传递,支持灵活的处理方式。
1. QEvent
事件基类
所有事件的基类,包含事件类型(Type
)和处理状态。
- 常用事件类型:
QEvent::MouseButtonPress
:鼠标按下QEvent::KeyPress
:键盘按下QEvent::Resize
:窗口大小变化QEvent::Timer
:定时器事件QEvent::Close
:窗口关闭
2. 事件处理方式
重写事件处理函数
QWidget
及派生类提供特定事件的虚函数(如 mousePressEvent
、keyPressEvent
),重写即可自定义处理。
-
示例代码:
cpp#include <QApplication> #include <QWidget> #include <QMouseEvent> #include <QDebug> class MyWidget : public QWidget { Q_OBJECT protected: // 重写鼠标按下事件 void mousePressEvent(QMouseEvent* event) override { if (event->button() == Qt::LeftButton) { qDebug() << "Left mouse pressed at:" << event->pos(); // 相对窗口坐标 } else if (event->button() == Qt::RightButton) { qDebug() << "Right mouse pressed at:" << event->globalPos(); // 全局屏幕坐标 } // 调用父类实现(确保默认行为,如窗口拖动) QWidget::mousePressEvent(event); } // 重写键盘按下事件 void keyPressEvent(QKeyEvent* event) override { if (event->key() == Qt::Key_Escape) { qDebug() << "Escape key pressed, closing window"; close(); } QWidget::keyPressEvent(event); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); MyWidget widget; widget.show(); return app.exec(); } #include "main.moc"
事件过滤器
通过 installEventFilter()
为对象安装事件过滤器,在事件到达目标对象前拦截处理。
-
示例代码:
cpp#include <QApplication> #include <QWidget> #include <QPushButton> #include <QEvent> #include <QDebug> class EventFilter : public QObject { Q_OBJECT protected: bool eventFilter(QObject* watched, QEvent* event) override { // 拦截按钮的点击事件 if (watched->inherits("QPushButton") && event->type() == QEvent::MouseButtonPress) { qDebug() << "Button click filtered!"; return true; // 事件被处理,不再传递 } // 其他事件交给默认处理 return QObject::eventFilter(watched, event); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; QPushButton button("Click Me", &window); EventFilter filter; button.installEventFilter(&filter); // 为按钮安装过滤器 window.show(); return app.exec(); } #include "main.moc"
重写 event()
函数
所有事件都会先经过 event()
函数,可在此处分发或拦截事件(适合处理自定义事件)。
-
示例代码:
cppbool MyWidget::event(QEvent* event) { if (event->type() == QEvent::Timer) { qDebug() << "Timer event received"; return true; // 处理定时器事件 } // 其他事件交给父类处理 return QWidget::event(event); }
五、绘图与图形(Qt Gui 模块)
Qt Gui 提供绘图功能,通过 QPainter
在 QPaintDevice
(如窗口、图片)上绘制图形、文本、图像等。
1. QPainter
绘图类
用于执行绘图操作,支持线条、矩形、椭圆、文本、图像等,需在 paintEvent()
中使用。
- 核心函数:
void drawLine(int x1, int y1, int x2, int y2)
:绘制直线。void drawRect(int x, int y, int w, int h)
:绘制矩形。void drawEllipse(const QRect& rect)
:绘制椭圆(矩形内接)。void drawText(int x, int y, const QString& text)
:绘制文本。void drawPixmap(const QRect& target, const QPixmap& pixmap)
:绘制图像。void setPen(const QPen& pen)
:设置画笔(线条颜色、宽度、样式)。void setBrush(const QBrush& brush)
:设置画刷(填充颜色、纹理)。
2. QPaintEvent
绘图事件
窗口需要重绘时(如显示、大小变化)触发,必须在 paintEvent()
中创建 QPainter
进行绘图。
-
示例代码 :
cpp#include <QApplication> #include <QWidget> #include <QPainter> #include <QPen> #include <QBrush> class DrawingWidget : public QWidget { Q_OBJECT protected: void paintEvent(QPaintEvent* event) override { Q_UNUSED(event); // 忽略事件参数 QPainter painter(this); // 在当前窗口绘图 // 绘制红色直线(宽度2px,虚线) QPen linePen(Qt::red, 2, Qt::DashLine); painter.setPen(linePen); painter.drawLine(50, 50, 250, 50); // 绘制蓝色填充矩形 painter.setPen(QPen(Qt::blue)); // 蓝色边框 painter.setBrush(QBrush(Qt::lightGray)); // 浅灰填充 painter.drawRect(50, 80, 200, 100); // 绘制绿色椭圆 painter.setPen(QPen(Qt::darkGreen)); painter.setBrush(QBrush(Qt::green)); painter.drawEllipse(QRect(100, 200, 100, 80)); // 绘制文本 painter.drawText(100, 320, "Qt Drawing Example"); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); DrawingWidget widget; widget.setWindowTitle("Drawing Example"); widget.resize(300, 350); widget.show(); return app.exec(); } #include "main.moc"
六、网络编程(Qt Network 模块)
Qt Network 提供跨平台的网络编程接口,支持 TCP、UDP、HTTP、FTP 等协议,简化网络通信开发。
1. QNetworkAccessManager
HTTP 客户端
用于发送 HTTP 请求(GET、POST 等),支持异步操作,通过信号返回响应。
-
核心函数:
QNetworkReply* get(const QNetworkRequest& request)
:发送 GET 请求。QNetworkReply* post(const QNetworkRequest& request, const QByteArray& data)
:发送 POST 请求。- 信号:
finished(QNetworkReply* reply)
(请求完成时)、downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
(下载进度)。
-
示例代码:
cpp#include <QApplication> #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkReply> #include <QDebug> int main(int argc, char *argv[]) { QApplication app(argc, argv); QNetworkAccessManager manager; // 发送GET请求 QNetworkRequest request(QUrl("https://www.qt.io")); QNetworkReply* reply = manager.get(request); // 连接请求完成信号 QObject::connect(reply, &QNetworkReply::finished, [&]() { if (reply->error() == QNetworkReply::NoError) { QByteArray data = reply->readAll(); qDebug() << "Response:" << data.left(500); // 输出前500字节 } else { qDebug() << "Error:" << reply->errorString(); } reply->deleteLater(); // 释放资源 app.quit(); // 退出应用 }); return app.exec(); }
2. TCP 通信(QTcpSocket
与 QTcpServer
)
-
QTcpServer
:TCP 服务器,监听端口并接受客户端连接。 -
QTcpSocket
:TCP 客户端/服务器端套接字,用于数据收发。 -
服务器示例:
cpp#include <QCoreApplication> #include <QTcpServer> #include <QTcpSocket> #include <QDebug> int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QTcpServer server; // 监听本地8080端口 if (!server.listen(QHostAddress::Any, 8080)) { qDebug() << "Server could not start:" << server.errorString(); return 1; } qDebug() << "Server listening on port 8080..."; // 连接新连接信号 QObject::connect(&server, &QTcpServer::newConnection, [&]() { QTcpSocket* socket = server.nextPendingConnection(); qDebug() << "New client connected:" << socket->peerAddress().toString(); // 接收客户端数据 QObject::connect(socket, &QTcpSocket::readyRead, [socket]() { QByteArray data = socket->readAll(); qDebug() << "Received:" << data; // 回复客户端 socket->write("Message received: " + data); }); // 客户端断开连接时释放资源 QObject::connect(socket, &QTcpSocket::disconnected, [socket]() { qDebug() << "Client disconnected"; socket->deleteLater(); }); }); return app.exec(); }
七、多线程(Qt Core 模块)
Qt 提供多种多线程方案,避免 UI 线程阻塞,提升程序响应性。
1. QThread
线程类
封装线程,通过重写 run()
函数定义线程执行逻辑。
-
核心函数:
void start(Priority priority = InheritPriority)
:启动线程(调用run()
)。void quit()
:退出线程事件循环。void wait(unsigned long time = ULONG_MAX)
:等待线程结束。- 信号:
started()
(线程启动时)、finished()
(线程结束时)。
-
示例代码:
cpp#include <QApplication> #include <QThread> #include <QDebug> #include <QPushButton> class WorkerThread : public QThread { Q_OBJECT protected: void run() override { qDebug() << "Worker thread ID:" << QThread::currentThreadId(); // 模拟耗时操作 for (int i = 0; i < 5; ++i) { msleep(1000); // 休眠1秒 qDebug() << "Working..." << i; } } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); qDebug() << "Main thread ID:" << QThread::currentThreadId(); QPushButton button("Start Worker"); WorkerThread thread; // 点击按钮启动线程 QObject::connect(&button, &QPushButton::clicked, [&]() { if (!thread.isRunning()) { thread.start(); } }); button.show(); return app.exec(); } #include "main.moc"
2. QRunnable
任务类
轻量级任务接口,配合 QThreadPool
实现线程池管理,适合短期任务。
-
示例代码:
cpp#include <QCoreApplication> #include <QRunnable> #include <QThreadPool> #include <QDebug> class MyTask : public QRunnable { public: void run() override { qDebug() << "Task running in thread:" << QThread::currentThreadId(); // 任务逻辑 } }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QThreadPool::globalInstance()->setMaxThreadCount(4); // 设置最大线程数 // 提交10个任务 for (int i = 0; i < 10; ++i) { QThreadPool::globalInstance()->start(new MyTask()); } // 等待所有任务完成 QThreadPool::globalInstance()->waitForDone(); return 0; }
八、Qt 开发最佳实践
-
内存管理:
- 利用对象树:为动态创建的部件设置父对象,避免内存泄漏。
- 使用
deleteLater()
而非直接delete
,确保事件处理完成后再销毁对象。
-
线程安全:
- 跨线程通信优先使用信号与槽(
Qt::QueuedConnection
),避免直接调用对象方法。 - 共享数据需加锁(
QMutex
),或使用线程安全容器(QAtomicInt
)。
- 跨线程通信优先使用信号与槽(
-
性能优化:
- 大量数据处理放入后台线程,避免阻塞 UI 线程。
- 使用
QStringBuilder
优化字符串拼接(%
运算符)。 - 绘图时使用
QPainter::beginNativePainting()
结合 OpenGL 加速。
-
跨平台适配:
- 文件路径使用
QDir
和QFileInfo
,避免硬编码斜杠(/
或\
)。 - 样式使用
QStyleSheet
而非平台特定 API,优先选择 Fusion 样式。
- 文件路径使用
本文只包含常用的方法,更多内容可参考 Qt 官方文档,包括 Qt Quick(QML 界面)、Qt Multimedia(多媒体)、Qt 3D(三维图形)等高级模块。通过合理利用 Qt 的跨平台特性和模块化设计,可高效开发从简单工具到复杂应用的各类软件。