Qt---Qt函数库

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 或其派生类实例,是事件循环的起点。

  • 示例代码

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

Qt 提供一系列模板容器类,替代 C++ 标准容器,优化了跨平台性能和 Qt 特性集成(如与 QVariant 兼容)。

  • QList<T>:最常用的动态数组,内部实现为数组+链表混合结构,支持快速随机访问和中间插入。

    • 核心函数:append()prepend()insert()removeAt()at()count()isEmpty()contains()

    • 示例:

      cpp 复制代码
      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()

    • 示例:

      cpp 复制代码
      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)。
  • 示例代码

    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 实现互斥:

      cpp 复制代码
      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):设置布局边缘留白。

  • 示例代码

    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 slotsprotected slotsprivate slots 区域,行为类似对应访问权限的函数。
  • 继承 QObject 并添加 Q_OBJECT 宏的类才能使用信号与槽(需通过 moc 工具预处理)。

4. 高级用法

  • lambda 表达式作为槽:简化短逻辑处理(Qt 5.0+ 支持):

    cpp 复制代码
    connect(button, &QPushButton::clicked, [this]() {
        qDebug() << "Button clicked, count:" << ++m_count;
    });
  • 信号连接信号:一个信号发射时触发另一个信号:

    cpp 复制代码
    connect(obj1, &MyObject::valueChanged, obj2, &MyObject::valueChanged);
  • 断开连接:不再需要时断开,避免悬空指针:

    cpp 复制代码
    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),重写即可自定义处理。

  • 示例代码:

    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() 函数,可在此处分发或拦截事件(适合处理自定义事件)。

  • 示例代码:

    cpp 复制代码
    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 进行绘图。

  • 示例代码

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

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

  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 的跨平台特性和模块化设计,可高效开发从简单工具到复杂应用的各类软件。

相关推荐
l1t1 天前
利用短整数类型和部分字符串优化DuckDB利用数组求解数独SQL
开发语言·数据库·sql·duckdb
权泽谦1 天前
从零搭建一个 PHP 登录注册系统(含完整源码)
android·开发语言·php
PieroPc1 天前
用python Streamlit 做个RapidOCR 文本识别系统
开发语言·python·ocr
暖木生晖1 天前
Javascript函数之匿名函数以及立即执行函数的使用方法?
开发语言·javascript·ecmascript
CodeKwang1 天前
Qt实战:自定义搜索跳转控件 | 附完整源码
qt·qt控件
say_fall1 天前
C语言容易被忽略的易错点(2)
c语言·开发语言
syker1 天前
NEWBASIC 2.06.7 API 帮助与用户使用手册
开发语言·人工智能·机器学习·自动化
Js_cold1 天前
Verilog运算符
开发语言·fpga开发·verilog
努力还债的学术吗喽1 天前
【项目】pyqt5基于python的照片整蛊项目
开发语言·python·qt
weixin_459548901 天前
Qt对话框设计
qt