1、Qt事件系统介绍
像windows这样的操作系统,是基于消息系统的。操作系统为每一个希望接收消息的线程维护一个消息队列。线程通过不断检索消息队列来获取消息,并对消息进行处理。在Qt框架中,事件系统是对消息机制进行的一种封装。在Qt框架中,消息被称之为事件。消息循环被称之为事件循环。在Qt框架中每种类型事件对应于一个事件类。
2、事件类型
(1)大多数事件类型对应于一个事件类,例如QResizeEvent对应于窗体尺寸调整事件,QPaintEvent对应于绘制事件,QKeyEvent对应于键盘敲击事件等。
(2)每一个事件类都是QEvent类的子类。他们都有针对特定事件类型的成员函数。
(3)有些事件类可能对应于多个事件类型。例如QMouseEvent类对应于鼠标按压事件,鼠标双击事件,鼠标移动事件等。
(4)QEvent类具有type()成员函数。他会返回事件对象的具体类型。
3、事件如何被处理
(1)Qt所有事件都是通过QCoreApplication::notify()成员函数进行分发的。QCoreApplication::notify()成员函数会调用接收对象的event()成员函数,完成事件的分发。
(2)每个从QObject基类派生的子类都有event()成员函数。event()成员函数通常并不直接处理事件。它通常根据所接收的事件类型,调用对应的事件响应成员函数对事件进行处理。
(3)事件循环处理方式如下:
事件循环的最外层先判断程序是否退出。内层循环优先处理投递事件(通过post函数投递的事件),之后处理自发事件(操作系统生成的事件),最后在对投递事件进行处理。
4、事件过滤器
(1)一个对象可以将自己作为目标对象的过滤器,从而可以查看和接收目标对象的所有事件。
(2)通过调用QObject::installEventFilter()函数,可以为目标对象增加一个事件过滤器对象。
(3)如果一个对象是目标对象的事件过滤器,那么它的eventFilter()函数会比目标对象优先处理事件。
(4)如果某个事件过滤器对象的eventFilter()函数返回true,则后续事件过滤器对象或目标对象可以接收到此事件。如果返回true,后续过滤器对象及目标对象都不会接收到此事件。
(5)通过调用QObject::removeEventFilter()函数移除一个事件过滤器对象。
5、如何自定义事件处理方式:
(1)重写一个类的事件响应函数
(2)重写一个类的event()函数
(3)将一个事件过滤器安装到一个目标对象中
(4)将一个事件过滤器安装到qApp对象中。通过这种方式事件过滤器对象将接收到程序发送给所有对象的事件。
(5)重写QApplication::notify()函数。
以上几种处理方式按照功能从弱到强进行排列。
6、事件发送方式
(1)投递方式:通过调用postEvent()函数,将一个事件放入目标对象所在线程的事件队列中。事件循环后续会对事件进行分发。
(2)发送方式:通过调用sendEvent()函数,通过直接调用QApplication::notify()函数将事件分发给目标对象。
(3)发送事件比投递事件能更快的被目标对象响应。
(4)投递方式可以实现某些类型事件的优化。例如:绘制事件、尺寸修改事件等。对于这些类型事件,事件循环可以将多个事件合并为一个事件,避免多次调用事件响应函数。
7、事件的接收与忽略
(1)在一个类的事件响应函数函数中,如果调用了事件对象的accept()成员函数,则事件不会再被其他对象接收。如果调用了事件对象的ignore()成员函数,Qt会尝试寻找其他接收对象。
(2)对于event()函数,如果返回true,则表示事件被接收。返回false则表示事件被忽略。
(3)事件默认是被接收的。QWidget默认事件响应函数会调用事件的ignore()成员函数。
(4)事件的accept()及ignore()函数是事件响应函数及event()函数之间传递事件是否被接收的工具。bool返回值是event()函数及notify()函数之间传递事件是否被接收的工具。