事件系统

发布时间 2023-03-29 23:33:25作者: 孤舟听雪

参考

  1. Qt之事件处理机制 - Fate0729 - 博客园 (cnblogs.com)
  2. Qt 事件之事件过滤器 | 爱编程的大丙 (subingwen.cn)
  3. Qt中的C++技术 16章Qt中的观察者模式

实例程序

  1. 重写关闭事件-关闭前确认
    假设为自定义Mainwindow
void closeEvent(QCloseEvent *event)
{
	    QMessageBox::Button btn = QMessageBox::question(this, "关闭窗口", "您确定要关闭窗口吗?");
       if(btn == QMessageBox::Yes)
       {
           // 接收并处理这个事件
           event->accept();
       }
       else
       {
           // 忽略这个事件
           event->ignore();
       }
}

什么是事件?

事件的产生

在单片机中按键操作的由中断处理程序处理。在qt中按键操作将产生一个事件对象。
其他设定的操作也将产生相应的事件对象。

事件的处理过程

首先qt 应用程序对象 QApplication 对象会维护一个 事件循环,产生的事件会被放到这个循环中。
根据事件处理的优先等级取出事件,被取出的事件直接发送给要处理它的对象(控件)。
如果有安装事件过滤器,那么会交给事件过滤器来过滤,过滤完毕后进行事件分发,分发给特定的事件处理函数进行处理。如果没有安装过滤,那么就直接分发并处理。

如果直接目标不进行处理,那么事件会被转交给他的父对象。
eventFilter()、event()通过返回值表示处理结果,因为具体的处理函数没有返回值(默认的没有),所以要在处理函数中调用accept()、ignore()表示事件是否处理完毕。

事件分发

[virtual] bool QObject::event([QEvent](qevent.html) *e)

根据事件的类型进行分发(调用事件处理函数),对于处理了的事件需要返回true,未处理的返回false

事件类型

QEvent::KeyPress 6 Key press (QKeyEvent).
QEvent::KeyRelease 7 Key release (QKeyEvent).
...

事件处理

QWidget 的protected 中已经定义了很多事件处理函数。按照默认方式处理事件时,调用QWidget的event()进行分发处理。

这里通过调用accept()表示处理该事件,ignore()表示不处理该事件。

自定义事件处理

QWidget中已定义的

需要子类化QWidget,然后重写该函数

QWdiget中未定义的

需要在event()中进行调用

事件过滤器

事件过滤器用于处理没有父子关系的控件之间,一个控件A的状态发生了变化对控件B、控件C、。。。控件N有影响。
使用观察者模式来实现这种功能,控件A作为被观察对象,其余控件是观察者。

事件过滤器的使用

  1. 被观察对象调用installFilter()来设置谁是观察者
  2. 观察者实现eventFilter()来对观察到的事件event 进行处理

事件在观察者和被观察对象之间的传递

参考3 图16.4
W有三个观察者,Observer1、2、3按顺序被设置,QEvent按照设置顺序被传递给观察者,首先是observer1,如果observer1 的event()返回false,表示事件还需要被处理,那么QEvent会被继续传递给下一个观察者。 如果observer1 返回true,表示事件被处理完毕,那么事件不再传递,其他观察者以及 被观察对象 不对该事件进行处理。

Qt中的应用

QScrollArea 对象观察widget,当widget的大小发生变化时,根据内容是否能够显示完全,及当前显示内容占全部内容的比例 决定是否显示scroll 及 滑块大小比例

官方示例

Mouse Button Tester

在自定义类中处理鼠标事件