文章目录
- 一、事件
- 1、基本概念
- 2、事件描述
- 3、事件循环
- 4、事件分发
- 4.1、QApplication::notify()
- 4.2、QObject::event()
- 5、事件传递
- 6、事件处理器
前言:
Qt 框架中的事件机制(Event Mechanism)是一种核心功能,它允许应用程序以事件驱动的方式响应各种外部和内部发生的动作。事件机制在 Qt 中扮演着至关重要的角色,无论是在用户界面的交互还是在后台处理数据时。它不仅确保了程序的响应性和灵活性,还大大降低了编程的复杂性,使开发者能够以更直观的方式来处理异步事件。
一、事件
1、基本概念
事件是由程序的内部或外部产生的事情或某种操作的统称。例如:用户按下鼠标或键盘就会产生一个鼠标或键盘事件,当窗口第一次绘制时会产生一个绘制事件。Qt中的事件主要来源于以下几个方面:
- 用户输入:如鼠标点击、键盘按键、触摸屏操作等。
- 系统事件:如窗口大小改变、系统时间变化、网络状态改变等。
- 定时器事件:通过QTimer类创建的定时器事件。
- 其他事件:如自定义事件、信号与槽机制触发的事件等
事件的作用:事件在 Qt 应用程序中扮演着至关重要的角色。它们是应用程序与用户或系统交互的基础,使得程序能够以非阻塞的方式响应外部的变化。通过事件,Qt 应用程序能够保持响应性和灵活性,同时简化复杂交互的处理逻辑。
2、事件描述
在Qt中使用抽象类
QEvent
类来描述事件,所有事件都是QEvent
的派生类。基本的QEvent
类只包含一个事件类型参数,QEvent
的子类包含额外的参数用来描述事件信息。事件类型使用QEvent::type
来表示,这个枚举类定义了Qt中有效的事件类型。Qt中常见的事件有
- 键盘事件(QKeyEvent)
- 鼠标事件(QMouseEvent)
- 拖放事件(QDragEvent 和 QDropEvent)
- 绘图事件(QPaintEvent)
- 焦点事件(QFocusEvent)
3、事件循环
通过
QApplication::exec()
开启事件循环,事件循环运行在一个无限循环中,不断检查是否有新的事件发生。当事件发生时,它们被加入到一个队列中。事件循环按照事件发生的顺序,从队列中取出并分发这些事件到相应的对象进行处理。这个过程是异步的,意味着事件的产生和处理是分离的,确保了应用程序的高效运行。事件循环是保持 Qt 应用程序响应性的关键。没有事件循环,应用程序将无法适时地响应用户输入、网络通信等事件。
4、事件分发
4.1、QApplication::notify()
在 Qt 的事件系统中,所有的事件(如鼠标点击、键盘输入、定时器事件等)都会经过
notify
方法进行分发。notify
方法原型如下:
bool notify(QObject *, QEvent *) Q_DECL_OVERRIDE;
默认情况下,
notify
方法会调用相应对象(接受事件的对象)的QObject::event
方法来处理这些事件。但可以通过重写notify
方法来定制事件的处理方式。具体来说,QApplication::notify
的作用包括:
- 事件分发:当 Qt 检测到一个事件(如鼠标点击、键盘输入等)时,它会调用 QApplication 的 notify 方法来分发这个事件。
- 事件过滤:在事件被发送到目标对象之前,你可以通过重写 notify 方法来过滤或修改事件。例如,你可以阻止某个特定类型的事件被发送到某个对象。
一般来说,直接重写 QApplication 的 notify 方法并不常见,因为这样做会影响整个应用程序的事件处理。但在某些特殊情况下,如实现全局的事件过滤器或自定义事件分发策略时,重写 notify 方法可能会非常有用。
4.2、QObject::event()
QObject::event
在 Qt 框架中是一个重要的成员函数,用于处理接收到的QEvent
对象,并将这些事件按照不同的类型,分发给不同的事件处理器。Qt中QObject::event
的源码如下:
bool QObject::event(QEvent *e)
{
switch (e->type()) {
case QEvent::Timer:
timerEvent((QTimerEvent*)e);
break;
case QEvent::ChildAdded:
case QEvent::ChildPolished:
case QEvent::ChildRemoved:
childEvent((QChildEvent*)e);
break;
// ...
default:
if (e->type() >= QEvent::User) {
customEvent(e);
break;
}
return false;
}
return true;
}
5、事件传递
如果对象没有处理该事件(即没有重写对应的事件处理函数或函数中没有调用event->accept()),Qt会尝试将该事件传递给其父对象。这个过程会一直持续到某个对象处理了事件或事件到达了顶级对象(如应用程序窗口)为止。这就是所谓的“事件冒泡”(event bubbling)。
6、事件处理器
如果Qt找到了一个与事件相关的对象,它会调用该对象的事件处理器(也称为事件处理函数),这些事件处理器都是虚函数,直接重写对应的虚函数就可以处理自己的业务。下面是常见的事件及事件处理器,如下:
- 鼠标事件(QMouseEvent)
- mousePressEvent(QMouseEvent *event): 处理鼠标按键的按下事件
- mouseReleaseEvent(QMouseEvent *event): 处理鼠标按键的释放事件。
- mouseMoveEvent(QMouseEvent *event): 处理鼠标移动事件。
- wheelEvent(QWheelEvent *event): 处理鼠标滚轮的滚动事件。
- 键盘事件(QKeyEvent)
- keyPressEvent(QKeyEvent *event): 处理键盘按键的按下事件。
- keyReleaseEvent(QKeyEvent *event): 处理键盘按键的释放事件。