事件是由系统或Qt本身产生的,以应对不断发生的情况。事件可以是鼠标事件、键盘事件或窗口显示等。
在Qt中,各种Widget已经封装了对各种事件的响应代码,对外的形式是各种信号。当使用Widget时,我们只需关注信号就可以了,而当自己实现一个Widget时,则需要自己实现一些事件响应代码。
在Qt中,一个事件对象继承自QEvent。Qt处理多达几百种事件,每种事件都用一个枚举类型来表示,如鼠标按下事件:QEvent::MouseButtonPress。
事件是通过函数event()来通知给对象的,继承看QObject,在QWidget的实现中,event()将转发大部分常见的事件类型给特定的事件处理器,如mousePressEvent,keyPressEvent以及paintEvent()。
安装事件过滤器
Qt事件模型的一个强大的特性就是一个QObject可以监控另一个QObject对象(该对象甚至不必感知另一对象的存在)。具体做法如下:
注册监控对象,即在目标对象上调用installEventFilter(),如:firstNameEdit->installEventFilter(this);
在监控者的eventFilter()函数中处理目标对象的事件。
Qt提供了在5个不同的层次上处理和过滤事件的方法:
重新实现一个特定的事件处理器。
例如,重新实现一个输入事件处理函数,如:mousePressEvent(),keyPressEvent()等。
重新实现QObject::event()。
通过重新实现event()函数,我们可以在事件到达特定的事件处理器之前处理它。不过在实现event()函数时,必须调用基类的event()函数以处理其他的情况。
在某个QObject对象上安装一个事件过滤器。
使用installEventFilter()函数,与之相关的目标对象的所有事件将首先被送到监控对象的eventFilter()函数中。
在QApplicatioin对象上安装珍上事件过滤器。
如果为qApp注册了一个事件过滤器,那么应用程序中的每个事件都首先被发送到该eventFilter()函数中,然后才转发给其他的事件过滤器。该方法通常用于调试。
创建QApplicatoin类的子类,并重新实现notify()函数。
Qt调用QApplication::notify()发送一个事件。重新实现该函数是获取所有被其他事件过滤器处理之前的事件的唯一方式。eventFilter()函数可以有多个,但notify()函数却只有一个。
QApplication::processEvents()
在Qt应用程序中,存在一个事件循环,对应着一个事件队列。对于单线程程序来说,只有一个事件队列。一个新事件首先添加到队列中,然后等待被处理。如果某个事件处理的时间有点长,就会影响其他事件的处理时间。此时,应用程序就会对其他事件无响应。为了解决此问题,一个比较简单的方法就是不停地调用QApplication::processEvents()函数。该函数告诉Qt去处理任何末决的事件,然后将控制权返还给调用者。事件上,Qapplication::exec()的简化模型就是在一个while循环中不断调用processEvents()函数。
代码实例如下:
static void artisticSleep(int sleepTime) { QTime time; time.restart(); while (time.elapsed() < sleepTime) QCoreApplication::processEvents(QEventLoop::AllEvents, 50); }