Qt---Qt函数库

发布于:2025-08-15 ⋅ 阅读:(16) ⋅ 点赞:(0)

Qt 框架采用模块化架构,核心模块包括 Qt Core(基础功能)、Qt Widgets(桌面 UI 组件)、Qt Gui(图形相关),扩展模块涵盖网络、数据库、多线程、Qt Quick 等。所有类均以 Q 为前缀(如 QObjectQWidget),无统一命名空间,但通过模块划分功能边界。

一、核心基础模块(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的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 以减少编码问题。

  • 示例代码

    #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. 容器类(QListQVectorQMap 等)

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 数据类型(如 intQStringQList 等),支持类型转换,常用于需要动态类型的场景(如 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(); // 输出 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()(定时器触发时发射)。
  • 示例代码

    #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 slotsprotected slotsprivate 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 及派生类提供特定事件的虚函数(如 mousePressEventkeyPressEvent),重写即可自定义处理。

  • 示例代码:
    #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 提供绘图功能,通过 QPainterQPaintDevice(如窗口、图片)上绘制图形、文本、图像等。

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 通信(QTcpSocketQTcpServer

  • 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 开发最佳实践

  1. 内存管理

    • 利用对象树:为动态创建的部件设置父对象,避免内存泄漏。
    • 使用 deleteLater() 而非直接 delete,确保事件处理完成后再销毁对象。
  2. 线程安全

    • 跨线程通信优先使用信号与槽(Qt::QueuedConnection),避免直接调用对象方法。
    • 共享数据需加锁(QMutex),或使用线程安全容器(QAtomicInt)。
  3. 性能优化

    • 大量数据处理放入后台线程,避免阻塞 UI 线程。
    • 使用 QStringBuilder 优化字符串拼接(% 运算符)。
    • 绘图时使用 QPainter::beginNativePainting() 结合 OpenGL 加速。
  4. 跨平台适配

    • 文件路径使用 QDirQFileInfo,避免硬编码斜杠(/\)。
    • 样式使用 QStyleSheet 而非平台特定 API,优先选择 Fusion 样式。

本文只包含常用的方法,更多内容可参考 Qt 官方文档,包括 Qt Quick(QML 界面)、Qt Multimedia(多媒体)、Qt 3D(三维图形)等高级模块。通过合理利用 Qt 的跨平台特性和模块化设计,可高效开发从简单工具到复杂应用的各类软件。


网站公告

今日签到

点亮在社区的每一天
去签到