一、概述
因为QT这个框架编译出的应用程序大多数都是基于窗口的,所以说我们对窗口进行操作,它多多少少都会产生对应的事件,那么说这个事件是怎么产生的?比如我们对窗口进行大小的变化,或者说鼠标拖到窗口进行移动,拿着鼠标或者键盘在窗口里进行相关的操作,比如说鼠标或者键盘这个按键被按下了、这个按键被释放了,对应的事件就产生了,当这个事件产生之后呢,窗口就需要对这个事件进行处理。因为QT的这个窗口是可以嵌套的,就是在一个窗口里可以有若干个子窗口,咱们这个鼠标或者键盘在哪一个子窗口里面进行了操作,那么这个事件就会被发送到哪一个子窗口里面进行处理。
二、事件的来源
1、系统产生的事件
系统产生的事件通常是由操作系统传递给应用程序的。例如,当用户点击鼠标、键盘按下、窗口大小改变等操作时,操作系统会将这些事件放入系统的消息队列中。QT的事件循环机制会不断地从系统消息队列中读取这些事件,并将其转换为QT事件(QEvent)进行处理。
2、应用程序自身产生
应用程序自身产生地事件是通过调用Qt提供地函数来触发地,列如,当需要重新绘制界面时,可以调用QWidget的update()函数,这会创建一个paintEvent事件,并将其通过QApplication::postEvent()函数放入Qt的事件队列中等待处理。另外,也可以使用sendEvent()函数直接将事件派发给指定的对象进行处理,而不是将其放入事件队列中。例子中提到的QWidget::repaint()函数就是直接发送一个重绘事件。
总结:无论事件是来自系统还是应用程序自身产生的,Qt的事件循环机制都会按照一定的顺序将这些事件发送给对应的对象进行处理。通过这种方式,Qt应用程序可以及时响应用户操作和自身的事件触发,保证了程序的正常运行和交互体验。
三、Qt事件的调度方式主要有两种:事件循环(Event Loop)和直接发送
1、事件循环(Event Loop):Qt的核心机制是基于事件循环的,即通过事件循环来实现事件的调度和处理。事件循环是一个不断运行的循环,它从事件队列中获取事件,并将其分发给相应的对象进行处理。Qt提供了一组主要的事件循环函数,包括QCoreApplication::exec()、QEventLoop::exec()和QWidget::eventLoop()等。通过调用这些函数,事件循环将被启动,并且会一直运行到程序退出或者事件队列为空。每当有事件到达时,事件循环会按照一定的规则将其发送到相应的目标对象进行处理。
2、直接发送事件:除了通过事件循环来调度事件,Qt也支持直接发送事件。这种方式下,事件不会被放入事件队列中,而是直接被发送给特定的目标对象进行处理。Qt提供了sendEvent()函数来实现直接发送事件。其中,sendEvent()函数会立即触发事件,不会将其放入事件队列;
注意:先处理Qt事件队列中的事件,直至为空,再处理系统消息队列中的消息,直至为空,在处理系统消息的时候会产生新的Qt事件,需要对其再次进行处理。
四、事件处理过程
1、事件派发
当事件产生之后,Qt使用应用程序对象调用notify()函数将事件发送到指定的窗口
//receiver:事件的接收者
//e:产生的事件
[override virtual] bool QApplication::notify(QObject *receiver, QEvent *e)
2、事件过滤
事件在发送过程中可以通过事件过滤器进行过滤,默认不对任何产生的事件进行过滤
//watched:过滤事件的对象
//event:对应的事件
//默认情况下:QT框架不会对任何事件进行过滤
//需要先给窗口安装过滤器,该事件才会触发
[virtual] bool eventFilter(QObject *watched, QEvent *event)
3、事件分发
当事件发送到指定窗口之后,窗口的事件会对收到的事件进行分类
//根据事件的类型进行分类,比如鼠标事件、键盘事件
[override virtual protected] bool QWidget::event(QEvent *event)
4、事件处理
事件分发器会将分类之后的事件(鼠标事件、键盘事件、绘图事件...)分发给对应的事件处理器函数进行处理,每个事件处理器函数都有默认的处理动作(我们也可以重写这些事件处理器函数),比如鼠标事件:
//鼠标按下
[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event);
//鼠标释放
[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event);
//鼠标移动
[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event);
Qt提供的这些事件处理器函数都是回调函数,也就是说作为使用者我们只需要指定函数的处理动作,关于函数的调用是不需要操心的,当某个事件被触发时,Qt框架会调用对应的事件处理器函数。