Qt中的事件处理机制(event)

版权声明:本博客内容可随意转载,但请标明出处! https://blog.csdn.net/weixin_38090427/article/details/83097355

Qt事件也就是Qt程序中出现的一系列“事情”,包括对用户操作做出反应时发出的鼠标或键盘事件等;以及系统内部自动发出的定时器事件等。总之,出现了这些事件后就需要对这些事件进行处理,处理的方法便是“事件处理机制”。

图1 Qt事件产生

以用户操作事件为例,其事件处理过程如下图。

图2 Qt事件处理过程

上述过程通过操作系统Qt平台的处理,将用户具体的一个操作指令(如鼠标点击)转化为一个Qt事件(即一个QEvent对象),这个Qt事件产生后,需要进行事件分发,所以就立刻被传给了函数virtual bool event (QEvent *e),这个QObject中的虚函数在其子类QWidget中被重新实现了,event()根据事件类型调用不同的事件处理函数。在事件处理函数中发送QT预定义的信号,最终调用信号关联的槽函数。(任意的QObject对象都具备事件处理的能力

而Qt平台(Qt程序)创建Qt事件的过程是这样的,程序的main()函数都会创建一个QApplication类对象,并调用其exec()函数,这个函数会使Qt应用程序进入事件循环,监听应用程序的事件。这样就可以使应用程序在运行时候接受发生的各种事件,一旦有事件发生,Qt便会创建一个相应的QEvent子类对象的事件来表示,然后传递给相应的QObject的event()函数进行事件分发。

Qt事件类都是继承于QEvent,其继承关系如图。

图3 Qt事件类继承关系

QWidget中的事件处理函数有很多,他们是protected virtual的,可以在他们的子类中重新实现,如keyPressEvent(QKeyEvent *event)、keyReleaseEvent(QKeyEvent *event)、mouseMoveEvent(QMouseEvent *event)、mousePressEvent(QMouseEvent *event)、mouseReleaseEvent(QMouseEvent *event)等。

仔细来看,事件与信号其实并无多大差别,从我们对其需求上来说,都只要能注册事件或信号响应函数,在事件或信号产生时能够被通知到即可。但有一项区别在于,事件处理函数的返回值是有意义的,我们要根据这个返回值来确定是否还要继续事件的处理,比如在QT中,事件处理函数如果返回true,则这个事件处理已完成,QApplication会接着处理下一个事件,而如果返回false,那么事件分派函数会继续向上寻找下一个可以处理该事件的注册方法。信号处理函数的返回值对信号分派器来说是无意义的。

    另外还有一个需要我们关注的问题是事件和信号处理时的优先级问题。在QT中,事件因为都是与窗口相关的,所以事件回调时都是从当前窗口开始,一级一级向上派发,直到有一个窗口返回true,截断了事件的处理为止。对于信号的处理则比较简单,默认是没有顺序的,如果需要明确的顺序,可以在信号注册时显示地指明槽的位置。

在QT中,事件使用了一个事件队列来维护,如果事件的处理中又产生了新的事件,那么新的事件会加入到队列尾,直到当前事件处理完毕后, QApplication再去队列头取下一个事件来处理。而信号的处理方式有些不同,信号处理是立即回调的,也就是一个信号产生后,他上面所注册的所有槽都会立即被回调。这样就会产生一个递归调用的问题,比如某个信号处理器中又产生了一个信号,会使得信号的处理像一棵树一样的展开。

猜你喜欢

转载自blog.csdn.net/weixin_38090427/article/details/83097355