type
status
date
slug
summary
tags
category
icon
password
事件系统是 Qt 核心机制,像多线程的信号和槽机制,也是基于事件以及事件循环系统驱动的。本文主要介绍 Qt 的事件系统的使用和基本概念,以便后续的源码分析。本文主要基于 Qt Quarterly —《Another Look at Events》,加上一些自己的见解。
1. 事件的原理
根据创建和调度的方式,事件可以分为三种:
- 自发事件(spontaneous event):由窗口系统产生的,在系统队列中由事件循环依次处理。
- 被发布事件(Posted event):由 Qt 或应用产生,在队列中由事件循环按顺序处理
- 被发送事件(Sent event):由 Qt 或应用产生,直接被发送到目标对象中。
一个 Qt 程序,通常在
main()
中,实例化一个应用(通常为 QCoreApplication
或其子类),并启动事件循环。事件循环的大致流程:2. 合成事件
Qt 应用可以合成事件,预定义的事件类型的范围为(
QEvent::None, QEvent::User
),为系统预留的事件。但也可以合成自定义事件,自定义事件的类型范围为[QEvent::User, QEvent::UserMax
]。事件创建完成后,可通过
QCoreApplication::postEvent()
或 QCoreApplication::sendEvent()
来分发。QCoreApplication::postEvent()
postEvent(QObject* receiver, QEvent* event)
方法传入的事件必须在堆上分配,该事件被处理后会自动删除。该方法会将事件添加到 receiver
所在线程的事件队列中,由事件循环处理。QCoreApplication::(QObject* receiver, QEvent* event)
sendEvent(QObject*, QEvent*)
方法传入 3. 自定义事件类型
Qt 允许创建自己的事件类型。事件在多线程应用中起到很大的作用。
- 相比于信号和槽机制、函数调用,事件可以以同步(
sendEvent
)或异步(postEvent
)的方式使用。
注:信号和槽其实也可以以同步(
Qt::BlockingQueuedConnection
)或异步(Qt::QueuedConnection
)的方式在多线程间使用。- 相比于信号和槽机制、函数调用,事件可以被过滤。
4. 事件处理和过滤
Qt中的事件可以在五个不同的层级上进行处理,由低到高分别为:
- 重新实现特定的事件处理器, 比如
paintEvent()
、mousePressEvent()
等
- 重新实现
QObject::event()
方法
- 在
QObject
对象上安装事件过滤器eventFilter
- 在
QCoreApplication
或其子类QGuiApplication
、QApplication
上安装事件过滤器eventFilter
- 重写
QCoreApplication::notify()
方法。
如果重写的方法没有覆盖所有事件,请最后调用默认的
notify()
方法