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() 方法