Qt---Qt函数库
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
或其派生类实例,是事件循环的起点。 -
示例代码:
#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
宏(启用元对象功能)。 -
示例代码:
#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的onValueChangedQObject::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
以减少编码问题。 -
示例代码:
#include <QString> #include <QDebug>int main() {QString str = "Hello, Qt!";qDebug() << "Length:" << str.length(); // 输出 9QString 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()
。 - 示例:
QList<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()
。 - 示例:
QMap<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)。
-
示例代码:
#include <QVariant> #include <QDebug>int main() {QVariant var(42); // 存储整数qDebug() << var.typeName(); // 输出 "int"qDebug() << var.toInt(); // 输出 42var.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()
(定时器触发时发射)。
-
示例代码:
#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)
:获取/设置全局调色板。
-
示例代码:
#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)
:为部件设置布局管理器(自动管理子部件位置)。
-
-
示例代码:
#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
实现互斥:QButtonGroup* 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)
:设置布局边缘留白。 -
示例代码:
#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()
:获取状态栏(自动创建)。
-
示例代码:
#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()
获取用户输入文本。
-
示例代码:
#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 | 阻塞队列:同队列连接,但信号发射线程会阻塞至槽函数执行完毕(跨线程) |
- 示例代码:
// 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+ 支持):
connect(button, &QPushButton::clicked, [this]() {qDebug() << "Button clicked, count:" << ++m_count; });
-
信号连接信号:一个信号发射时触发另一个信号:
connect(obj1, &MyObject::valueChanged, obj2, &MyObject::valueChanged);
-
断开连接:不再需要时断开,避免悬空指针:
disconnect(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
),重写即可自定义处理。
- 示例代码:
#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()
为对象安装事件过滤器,在事件到达目标对象前拦截处理。
- 示例代码:
#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()
函数,可在此处分发或拦截事件(适合处理自定义事件)。
- 示例代码:
bool 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
进行绘图。
- 示例代码:
#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)
(下载进度)。
-
示例代码:
#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 客户端/服务器端套接字,用于数据收发。 -
服务器示例:
#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()
(线程结束时)。
-
示例代码:
#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
实现线程池管理,适合短期任务。
- 示例代码:
#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 的跨平台特性和模块化设计,可高效开发从简单工具到复杂应用的各类软件。