Qt事件分类
-
Spontaneous 事件
由窗口系统产生,它们被放到系统队列中,通过事件循环逐个处理。
本类事件通常是Windows System把从系统得到的消息,比如鼠标按键、键盘按键等, 放入系统的消息队列中。 Qt事件循环的时候读取这些事件,转化为QEvent,再依次逐个处理。
-
Posted 事件
由Qt或应用程序产生,它们被Qt组成队列,再通过事件循环处理。
调用QApplication::postEvent()来产生一个posted类型事件。
例如:QWidget::update()函数,当需要重新绘制屏幕时,程序调用update()函数。其实现的原理是new出一个paintEvent,调用 QApplication::postEvent(),将其放入Qt的消息队列中,等待依次被处理。
-
Send事件
由Qt或应用程序产生,但它们被直接发送到目标对象。
调用QApplication::sendEvent()函数来产生一个send类型事件。
send 类型事件不会放入队列, 而是直接被派发和处理, QWidget::repaint()函数用的就是这种方式。
QObject类
QObject三大职责
-
内存管理
-
内省(intropection)
-
事件处理机制
任何一个想要接受并处理事件的对象均须继承自QObject,可以重写QObject::event() 来处理事件,也可以由父类处理。
事件处理与过滤
Qt提供了5个级别来处理和过滤事件。
-
重新实现特定的event handler
重新实现像mousePressEvent(), keyPressEvent()和paintEvent()这样的event Handler是目前处理event最普通的方式。 -
重新实现QObject::event()
通过重新实现event(),我们可以在事件到达特定的event handler之前对它们作出处理。 -
安装一个event filter到一个单独的QObject
一个对象用installEventFilter注册了, 发到目标对象的所有事件都会先发到监测对象的eventFilter()。如果同一个object安装了多个event filter, filter会依次被激活, 从最近安装的回到第一个。例如:
textField.installEventFilter(obj),如果有事件发送到textField组件时,会先调用obj->eventFilter()函数,然后才会调用textField.event()。 -
在QApplication对象上安装event filter
一个event filter被注册到唯一的QApplication对象, 程序里发到每个对象的每个事件在发到其他event filter之前,都要首先发到这个eventFilter()。 -
子类化QApplication并重新实现notify()
Qt调用QApplication::notify()来发出事件,在任何event filter得到之前, 重新实现这个函数可以得到所有事件。
自定义事件
阻塞型事件:事件发送后需要等待处理完成
bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
事件生命周期由应用程序自身管理,同时支持栈事件对象和堆事件对象的发送。
非阻塞型发送:事件发送后立刻返回,事件被发送到事件队列等待处理
void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority)
只能发送堆事件对象,事件被处理后由Qt平台销毁。
事件的传递
对于某些会被转发的事件, 包括: 鼠标、滚轮、按键等事件。如果在整个事件的派发过程结束后还没有被处理, 那么这个事件将会向上转发给它的父widget,直到最顶层窗口。
比如:事件可能最先发送给QCheckBox, 如果QCheckBox没有处理, 那么由QGroupBox接着处理;如果QGroupBox仍然没有处理, 再送到QDialog, 因为QDialog已经是最顶层widget, 所以如果QDialog再不处理, QEvent将停止转发。
如何终止事件传递?
QApplication::notify(), QObject::eventFilter(), QObject::event() 通过返回bool值来表示是否继续传递。“真”表示已经处理,不再传递, “假”表示事件需要继续传递。
另一种是调用QEvent::accept() 或 QEvent::ignore()对事件进行标识。前者用来告诉Qt,事件处理函数“接收”了这个事件,不要再传递;后者则告诉Qt,事件处理函数“忽略”了这个事件,需要继续传递。