第16章 Qt中的观察者模式
一个GUI应用程序常常提供了多种视图来查看同一个数据对象,一旦该对象发生变化,所有视图都会发生变化。
例如Excel中对数据的多种显示和处理方式:

我们可以使用观察者(Observer)模式来实现这一功能:
- 被显示的数据被称为主对象(Subject)
- 显示这些数据的视图被称为观察者(Observer)
Qt中的信号与槽机制使用了观察者模式:
- 发出信号的对象就是该模式中的主对象;
- 提供槽函数的对象就是该模式中的观察者
- connect函数连接一个信号与一个槽,实际上对主对象添加了一个观察者;反之,disconnect函数删除了一个观察者。
- 当信号产生时,所有观察者的槽函数都会被调用,观察者可以更新自己的状态。
信号与槽提供了一种简单的观察者模式。然而,在Qt中的事件处理机制中,需要使用者显式地使用该模式。
16.1 事件处理机制
在应用程序和用户交互过程中,会产生各种事件(Event),如鼠标单击、移动事件,键盘按键事件等等;
操作系统也会向应用程序发送各种事件,如窗口或对话框对象首次被显示在屏幕上时,Windows系统会向该对象发送“绘制”事件(paint),通知该对象绘制自己。
应用程序本身也可以产生事件,如一个计时器(QTimer)对象会周期性地发送“计时时间到”时间,等等。
在Qt中,使用QEvent类来描述事件。该类有很多子类,对各种类型的事件进行描述,如QMouseEvent,QPaintEvent, QTimerEvent等等。
为了方便对于这些事件的描述,QEvent类中定义了相应的枚举常量,如QEvent::Timer等等。
对于底层事件,通常使用者无需修改相应的处理函数;当需要不同与Qt默认的方式处理事件时,可以通过重写事件处理函数来实现。
16.2 事件滤波器 (Event Filter)
对于具有父子关系的两个控件来说,子控件检测到事件,可以通过返回false的方式将事件传递给父控件处理。
然而对于没有父子关系的两个控件,这种事件传递机制就会失效。相应的解决方案时Qt的事件滤波器(Event Filter)
设置QScrollArea为另一控件的观察者示例代码:
void QScrollArea::setWidget(QWidget* widget) {
...
widget->installEventFilter(this);
...
}
bool QScrollArea::eventFilter(QObject* o, QEvent* e) {
if (o == d->widget && e->type() == QEvent::Resize)
d->updateScrollBars();
return false;
}
本文整理自《Qt中的C++技术》张波 著

浙公网安备 33010602011771号