编程进阶网 编程进阶网
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接

杨充

专注编程 · 终身学习者
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接
  • README
  • Android提升进阶

  • iOS开发和进阶

  • Web开发和进阶

  • Linux应用开发

    • README
    • QML基础入门

    • QT核心库实践

      • README
      • 核心功能基础
      • 并发与多线程
      • 文件与IO系统
      • 日期与时间处理
      • 网络与序列化
      • QT事件系统
        • 6.1 事件系统
          • 6.1.1 事件处理
          • 6.1.2 自定义事件
          • 6.1.3 事件系统
        • 6.2 事件循环
          • 6.2.1 事件循环流程
          • 6.2.2 核心原理
          • 6.2.3 事件队列
          • 6.2.4 处理事件
          • 6.2.5 处理任务
        • 6.2 QT事件处理
          • 6.2.2 事件处理函数
          • 6.2.3 事件过滤器
          • 6.2.4 自定义事件
          • 6.2.5 定时器事件
        • 6.3 QEvent
          • 6.3.1 QEvent概述
          • 6.3.2 常见QEvent子类
        • 6.4 事件处理
          • 6.4.1 重写事件函数
          • 6.4.2 重写event()函数
          • 6.4.3 安装事件过滤器
          • 6.4.4 事件传播
      • 信号与槽机制
      • 多媒体的应用
      • 容器类和算法
      • 高级编程技巧
    • Linux实践开发

  • Apps
  • Linux应用开发
  • QT核心库实践
杨充
2025-08-21
目录

QT事件系统

# 06.QT事件系统

  • 6.1 事件系统
    • 6.1.1 事件处理
    • 6.1.2 自定义事件
    • 6.1.3 事件系统
  • 6.2 事件循环
    • 6.2.1 事件循环流程
    • 6.2.2 核心原理
    • 6.2.3 事件队列
    • 6.2.4 处理事件
    • 6.2.5 处理任务
  • 6.2 QT事件处理
    • 6.2.2 事件处理函数
    • 6.2.3 事件过滤器
    • 6.2.4 自定义事件
    • 6.2.5 定时器事件
  • 6.3 QEvent
    • 6.3.1 QEvent概述
    • 6.3.2 常见QEvent子类
  • 6.4 事件处理
    • 6.4.1 重写事件函数
    • 6.4.2 重写event()函数
    • 6.4.3 安装事件过滤器
    • 6.4.4 事件传播

# 6.1 事件系统

Qt 的事件处理机制是其核心功能之一,用于处理用户输入、窗口事件、定时器事件等。

Qt 的事件系统基于事件循环(Event Loop)和事件过滤器(Event Filter),开发者可以通过重写事件处理函数或安装事件过滤器来拦截和处理事件。

# 6.1.1 事件处理

  • QEvent:事件基类
  • QCoreApplication:事件循环管理
  • QEventLoop:事件循环
  • QAbstractEventDispatcher:事件分发器抽象

# 6.1.2 自定义事件

  • 自定义事件类型
  • 事件过滤器(eventFilter)
  • 发送事件(sendEvent/postEvent)

# 6.1.3 事件系统

功能:处理用户输入、定时器事件、自定义事件等。核心类:

  • QEvent:所有事件的基类。
  • QCoreApplication:管理事件循环。
  • QTimer:定时器事件。
  • QKeyEvent、QMouseEvent:键盘和鼠标事件。

# 6.2 事件循环

# 6.2.1 事件循环流程

Qt 应用程序的核心是事件循环,它负责接收和分发事件。事件循环由 QCoreApplication::exec() 启动。

#include <QApplication>
#include <QDebug>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    qDebug() << "Event loop started";
    return app.exec(); // 启动事件循环
}
1
2
3
4
5
6
7
8

事件循环工作流程:

  1. 等待事件: 监听系统事件(鼠标、键盘、定时器、网络等)
  2. 分发事件: 将事件分发给相应的对象处理
  3. 处理事件: 调用相应的事件处理函数
  4. 更新界面: 重绘需要更新的界面元素
  5. 循环继续: 回到步骤1,直到应用退出

# 6.2.2 核心原理

每个 Qt 应用至少有一个事件循环(在主线程中,由 QApplication::exec() 启动)。它不停地做一件事:

  1. 检查事件队列:是否有新事件到来?(如鼠标点击、键盘输入、定时器超时、网络数据到达、重绘请求等)。
  2. 处理事件:将事件分发给相应的目标对象(QObject)。
  3. 处理任务:处理事件循环本身需要执行的任务,比如处理排队的信号槽调用(Qt 的默认连接方式,Qt::AutoConnection,在跨线程时是异步的,但在同一线程内是同步的,其实相当于直接函数调用)。
while (isRunning) {
    // 1. 检查事件队列,处理事件
    while (eventQueue.hasEvents()) {
        processNextEvent();
    }

    // 2. 处理其他任务(如信号槽调用)
    processPendingTasks();

    // 3. 进入休眠,直到有事件到来或定时器触发
    waitForMoreEvents();
}
1
2
3
4
5
6
7
8
9
10
11
12

事件循环处理事件的流程如下:

  1. 事件产生:事件由操作系统、硬件或应用程序内部产生。
  2. 事件投递:事件被放入事件队列(通过 postEvent()或系统事件投递)。
  3. 事件分发:事件循环从队列中取出事件,并分发给目标对象(QObject)。
  4. 事件处理:目标对象的 event()方法被调用,进而调用特定的事件处理函数(如 mousePressEvent()、keyPressEvent()等)。

Qt 事件循环的核心思想是事件驱动编程模型,其基本工作流程如下:

+----------------+     +----------------+     +----------------+
|  事件生产者      |     |  事件队列       |     |  事件消费者     |
| (硬件/系统/应用) |---->| (FIFO缓冲区)   |---->| (QObject子类)  |
+----------------+     +----------------+     +----------------+
        |                      |                      |
        | 生成事件              | 存储/排序             | 处理事件
        | (鼠标点击/网络数据等) |                      | (重绘/业务逻辑)
1
2
3
4
5
6
7

核心原则:

  1. 非阻塞等待:在没有事件时进入高效休眠状态
  2. 事件优先级:不同类型事件有不同处理优先级
  3. 线程隔离:每个线程有独立的事件队列和循环
  4. 统一调度:所有异步操作最终都转化为事件处理

# 6.2.3 事件队列

事件队列的组成,事件队列(Event Queue)是一个先进先出(FIFO)的数据结构,用于存储待处理的事件。事件包括:

  1. 用户输入事件:鼠标点击、键盘输入等。
  2. 系统事件:窗口重绘、定时器超时、网络数据到达等。
  3. 自定义事件:用户通过 QCoreApplication::postEvent()发送的事件。

多级优先级队列,Qt 使用复杂的数据结构管理事件队列:

// 伪代码表示事件队列结构
class QEventLoop {
    QQueue<QEvent*> highPriorityEvents;   // 高优先级事件(重绘、定时器)
    QQueue<QEvent*> normalEvents;          // 普通事件(用户输入)
    QQueue<QEvent*> lowPriorityEvents;     // 低优先级事件(空闲任务)
    QQueue<DeferredDeleteEvent> deleteLaterEvents; // 延迟删除事件
};
1
2
3
4
5
6
7

事件处理优先级(从高到低):

  1. 定时器事件:保证精确时间触发
  2. 重绘事件:避免界面卡顿
  3. 输入事件:响应用户交互
  4. 网络事件:处理I/O操作
  5. 空闲事件:执行低优先级任务

事件循环核心算法

bool QEventLoop::processEvents() {
    while (!exitRequested) {
        // 步骤1:处理高优先级事件
        while (hasHighPriorityEvents()) {
            QEvent *e = dequeueHighPriorityEvent();
            dispatchEvent(e); // 分发到目标对象
        }
        
        // 步骤2:处理普通事件
        if (hasEvents()) {
            QEvent *e = dequeueEvent();
            dispatchEvent(e);
            continue; // 返回处理高优先级事件
        }
        
        // 步骤3:处理延迟删除
        processDeferredDeletion();
        
        // 步骤4:处理空闲任务
        if (hasIdleTasks()) {
            processIdleTasks();
        }
        
        // 步骤5:进入高效等待
        if (noEventsPending) {
            waitForEvents(timeout); // 使用epoll/kqueue/select等系统调用
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 6.2.4 处理事件

事件循环在每次迭代中检查事件队列:

  • 非阻塞检查:如果有事件,立即处理。
  • 阻塞等待:如果队列为空,事件循环会进入休眠状态,直到有事件到来。唤醒条件包括:
    • 新事件到达(如用户输入)。
    • 定时器超时。
    • 外部唤醒(如调用 QCoreApplication::wakeUp())。

# 6.2.5 处理任务

# 6.2 QT事件处理

# 6.2.2 事件处理函数

Qt 中的事件处理函数是 QObject 的成员函数,可以通过重写这些函数来处理特定事件。

1.常用事件处理函数

  • mousePressEvent(QMouseEvent *):处理鼠标按下事件。
  • mouseMoveEvent(QMouseEvent *):处理鼠标移动事件。
  • keyPressEvent(QKeyEvent *):处理键盘按下事件。
  • paintEvent(QPaintEvent *):处理绘制事件。
  • resizeEvent(QResizeEvent *):处理窗口大小调整事件。
  • closeEvent(QCloseEvent *):处理窗口关闭事件。

2.示例:重写事件处理函数

#include <QWidget>
#include <QMouseEvent>
#include <QDebug>

class MyWidget : public QWidget {
protected:
    void mousePressEvent(QMouseEvent *event) override {
        qDebug() << "Mouse pressed at:" << event->pos();
    }

    void keyPressEvent(QKeyEvent *event) override {
        qDebug() << "Key pressed:" << event->text();
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyWidget widget;
    widget.resize(200, 200);
    widget.show();
    return app.exec();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 6.2.3 事件过滤器

事件过滤器允许一个对象拦截并处理另一个对象的事件。

1.安装事件过滤器

#include <QApplication>
#include <QWidget>
#include <QDebug>

class EventFilter : public QObject {
protected:
    bool eventFilter(QObject *obj, QEvent *event) override {
        if (event->type() == QEvent::MouseButtonPress) {
            qDebug() << "Mouse pressed in:" << obj->objectName();
            return true; // 事件已被处理
        }
        return QObject::eventFilter(obj, event);
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QWidget widget;
    widget.setObjectName("MainWidget");
    EventFilter filter;
    widget.installEventFilter(&filter); // 安装事件过滤器
    widget.resize(200, 200);
    widget.show();
    return app.exec();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 6.2.4 自定义事件

Qt 允许开发者创建和发送自定义事件。

1.定义自定义事件

#include <QEvent>

const QEvent::Type MyCustomEventType = static_cast<QEvent::Type>(QEvent::User + 1);

class MyCustomEvent : public QEvent {
public:
    MyCustomEvent(const QString &message)
        : QEvent(MyCustomEventType), m_message(message) {}
    QString message() const { return m_message; }
private:
    QString m_message;
};
1
2
3
4
5
6
7
8
9
10
11
12

2.发送自定义事件

#include <QApplication>
#include <QWidget>
#include <QDebug>

class MyWidget : public QWidget {
protected:
    void customEvent(QEvent *event) override {
        if (event->type() == MyCustomEventType) {
            MyCustomEvent *customEvent = static_cast<MyCustomEvent *>(event);
            qDebug() << "Custom event received:" << customEvent->message();
        }
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    MyWidget widget;
    widget.resize(200, 200);
    widget.show();

    // 发送自定义事件
    MyCustomEvent event("Hello, Custom Event!");
    QApplication::postEvent(&widget, &event);

    return app.exec();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 6.2.5 定时器事件

# 6.3 QEvent

在 Qt 中,QEvent 是所有事件类的基类。Qt 的事件系统用于处理各种用户交互、系统事件和应用程序内部事件。

每个事件都是一个 QEvent 或其子类的实例,Qt 通过事件循环将这些事件分发给相应的对象(如窗口部件)进行处理。

# 6.3.1 QEvent概述

QEvent 是 Qt 事件系统的核心类,所有事件都继承自 QEvent。

  • 事件可以是用户输入(如鼠标点击、键盘按键)、系统事件(如定时器事件、窗口事件)或自定义事件。
  • 事件通过 QObject::event() 或特定的事件处理函数(如 mousePressEvent())进行处理。

# 6.3.2 常见QEvent子类

Qt 提供了许多内置的事件类型,以下是一些常见的 QEvent 子类:

事件类型 描述
QMouseEvent 鼠标事件(点击、移动、释放等)。
QKeyEvent 键盘事件(按键按下、释放)。
QResizeEvent 窗口或部件大小改变事件。
QPaintEvent 绘制事件,用于重绘部件。
QTimerEvent 定时器事件,用于处理定时器超时。
QCloseEvent 窗口关闭事件。
QFocusEvent 焦点事件(获得焦点、失去焦点)。
QWheelEvent 鼠标滚轮事件。
QDropEvent 拖放事件。
QDragEnterEvent 拖拽进入事件。
QHoverEvent 鼠标悬停事件。
QContextMenuEvent 上下文菜单事件(右键菜单)。
QInputMethodEvent 输入法事件。
QActionEvent 与 QAction 相关的事件。
QCustomEvent 自定义事件(已弃用,推荐使用 QEvent 的子类)。

# 6.4 事件处理

Qt 提供了多种方式来处理事件:

# 6.4.1 重写事件函数

在自定义的 QWidget 或 QObject 子类中,重写特定的事件处理函数。例如:

class MyWidget : public QWidget {
protected:
    void mousePressEvent(QMouseEvent *event) override {
        qDebug() << "Mouse pressed at:" << event->pos();
    }

    void keyPressEvent(QKeyEvent *event) override {
        qDebug() << "Key pressed:" << event->text();
    }
};
1
2
3
4
5
6
7
8
9
10

# 6.4.2 重写event()函数

通过重写 QObject::event() 函数,可以处理所有事件:

class MyWidget : public QWidget {
protected:
    bool event(QEvent *event) override {
        if (event->type() == QEvent::MouseButtonPress) {
            qDebug() << "Mouse press event detected!";
            return true; // 事件已处理
        }
        return QWidget::event(event); // 其他事件交给父类处理
    }
};
1
2
3
4
5
6
7
8
9
10

# 6.4.3 安装事件过滤器

通过 QObject::installEventFilter(),可以监听其他对象的事件:

class MyFilter : public QObject {
protected:
    bool eventFilter(QObject *obj, QEvent *event) override {
        if (event->type() == QEvent::KeyPress) {
            qDebug() << "Key press event filtered!";
            return true; // 事件已处理
        }
        return QObject::eventFilter(obj, event); // 其他事件交给父类处理
    }
};

// 使用事件过滤器
MyFilter filter;
myWidget->installEventFilter(&filter);
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 6.4.4 事件传播

  • 事件传播:事件会从子对象向父对象传播,直到被处理或到达顶层对象。
  • 事件接受与忽略:通过 QEvent::accept() 和 QEvent::ignore() 可以控制事件是否继续传播。
上次更新: 2026/06/10, 11:13:41
网络与序列化
信号与槽机制

← 网络与序列化 信号与槽机制→

最近更新
01
信号崩溃快速排查
06-15
02
CoreDump破案
06-15
03
perf火焰图实战
06-15
更多文章>
Theme by Vdoing | Copyright © 2019-2026 杨充 | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式