Qt事件机制详解

  • A+
所属分类:Qt专栏

事件机制的流程

Qt事件机制详解

产生事件

1.调用QApplication::postEvent(), 例如QWidget::update()函数,当需要重新绘制屏幕时,程序调用update()函数,new出来一个paintEvent,调用 QApplication::postEvent(),将其放入Qt的消息队列中,等待依次被处理;postEvent()中事件对象的生命期由Qt平台管理,只支持分配在堆上的事件对象,事件被处理后由Qt平台销毁。这种方式是异步处理事件,Qt的事件循环是异步的,当调用QApplication::exec()时,就进入了事件循环,先处理Qt事件队列中的事件, 直至为空,再处理系统消息队列中的消息, 直至为空, 处理系统消息的时候会产生新的Qt事件, 需要对其再次进行处理。

2.另一种方式是调用sendEvent()函数,事件不会放入队列, 而是直接被派发和处理, QWidget::repaint()函数用的就是阻塞型的。sendEvent()中事件对象的生命期由Qt程序管理,支持分配在栈上和堆上的事件对象;调用QApplication::sendEvent的时候, 消息会立即被处理,是同步的。实际上QApplication::sendEvent()是通过调用QApplication::notify(), 直接进入了事件的派发和处理环节。

事件的派发

  • bool QApplication::notify(QObject *receiver, QEvent *e)
  • bool Qapplication eventFilter(QObject *watched, QEvent *event)
  • Qt控件 bool eventFilter(QObject *watched, QEvent *event)

这四种属于事件的派发函数,事件从产生为止,不是直接将事件发送到接收者手中处理,而是需要经历一连串的派发,这个派发过程其实就是安装的一系列过滤器,如果某个事件被过滤器过滤了,则事件到此停止,不再派发,那么,实际的接收者也就不再接收到这个事件了。这几个函数返回值都是bool,返回false,则继续派发该事件给其他过滤器,否则不再派发。

事件接收者处理

Qt控件 bool event(QEvent *event),经历了一系列派发,如果事件没有被过滤掉,那么最终会到达接收者这里,接收者会调用事件处理函数来处理。可以在事件处理函数中对事件进行标识(QEvent::ignore() 或 QEvent::accept()),该标识操作在bool event(QEvent *event)函数中设置无效。如果返回值是 true,并且事件对象设置了accept(),那么QT会认为这个事件已经处理完毕,不会再将这个事件发送给父组件,而是会继续处理事件队列中的下一事件。event类, 有一个成员函数 isAccepted() 可以用来判别event事件是已被接受处理或被拒绝处理。如果传入的事件已被识别并且event函数处理完毕,则需要返回 true,否则返回 false。Ignore:表示该事件未处理完毕,会将事件传递给父控件;accept:表示该事件处理完毕,不会再传递给父控件。

 

事件的转发

如果在整个事件的派发过程结束后还没有被处理, 那么这个事件将会向上转发给它的父widget, 直到最顶层窗口。一般情况下,event处理函数里,返回true表示accept,返回false表示向上级传播。但closeEvent是个特殊情形,accept表示quit,ignore表示取消,所以最好在closeEvent显式调用accept和ignore。QEvent默认为accept,QWidget默认调用ignore,如果不想让事件传递给父控件,则重写事件处理函数即可;如果想让事件传递给父控件,则重写事件处理函数,并且调用父类的事件处理函数作为返回值(千万不要忘了调用父类的事件处理函数)。

腾讯云推广
阿拉灯aladeng