操作系统将获取到的诸如鼠标键按下(mousePressEvent)、鼠标键弹起(mouseReleaseEvent)、键盘键按下(keyPressEvent)、键盘键弹起(keyReleaseEvent)等事件,压入事件队列中。Qt应用程序的事件循环从事件队列中弹出事件,转化为QEvent对象,分发给特定的组件对象。收到事件的组件对象的event方法会被调用,以完成对事件的处理。event方法在对某些事件的处理过程中,会根据具体的事件类型调用相应的信号函数。信号函数再调用与之连接的槽函数。槽函数中包含了用户编写的,针对该事件的业务处理代码。
应用程序产生事件的方式分为两种。一种是通过QApplication类的postEvent方法寄出事件。例如当需要重绘窗口时,应用程序可以调用QWidget类的update方法。该方法会创建一个表示绘制事件的paintEvent对象,并将其作为参数传递给QApplication类的postEvent方法。postEvent方法将绘制事件压入事件队列。在针对该事件的处理过程中完成窗口绘制动作。另一种是通过QApplication类的sendEvent方法发送事件。所发送的事件不会进入事件队列,而是直接被派发和处理。QWidget类的repaint方法就属于这种情况。
寄出事件的postEvent方法只要将事件压入事件队列即可返回,并不需要等待事件被处理完,因此QWidget类的update方法不会阻塞,而发送事件的sendEvent方法则需要在事件被处理完以后才会返回,因此QWidget类的repaint方法会导致阻塞。
被postEvent方法寄出的事件对象,必须在堆上动态创建,事后由Qt负责销毁,而被sendEvent方法发送的事件对象,既可以在堆上动态创建,也可以在栈上静态创建,其生命周期由应用程序自己管理。