The Event System
一、事件
不同于广义上的事件,在程序中事件通常指由于某些动作而产生的响应的消息。
Qt常见的事件类型包括鼠标事件、键盘事件、拖放事件、滚轮事件、绘屏事件、定时事件、焦点事件、移动事件、尺寸该表事件、窗口隐藏显示事件等。
本质上Qt就是利用QApplication进行事件的分发,而利用QObject进行事件的接收和处理的。
流程框图分发、接收、处理的流程如下(Qt源码函数):
图1 流程框图
二、事件的种类
事件主要分为两类:
1)系统事件:例如键盘鼠标等的触发事件;
2)程序产生事件:Qt主要有两种,例如重绘中的update()是调用postEvent(),将事件放进消息队列中,等待依次被处理,而repaint()是调用sendEvent(),将事件直接派发和处理,不进入队列中。
三、事件的调度方式
事件的调度方式主要有两种:
1)同步
sendEvent()就是同步的,而实际上sendEvent()是调用QApplication::notify()从而直接进行事件的派发和处理。
2)异步
postEvent()就是异步的,此时调用QApplication::exec(),进入Qt的事件循环中。例如keyPressEvent,keyReleaseEvent,mousePressEvent,mouseReleaseEvent都是异步的。
四、事件的处理应用
任何一个想要接受并处理事件的对象均须继承自QObject,Qt拥有五种处理事件的方式,处理的强度由弱到强。
1、重新实现一个特定的事件
Qt中QEvent表示事件处理结果的有两个函数,分别为accept()和ignore(),默认是ignore(),如果在特定事件中将结果处理为accept(),那么事件将不再传播。
示例如下:
void Widget::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Key_Escape) {
……
} else {
//将除了Esc的按键返回给父控件QWidget处理
QWidget::keyPressEvent(event);
}
}
2、重新实现QObject::event()
bool QWidget::event(QEvent *event)
{
if (e->type() == QEvent::KeyPress) {
QKeyPressEvent *keyEvent = (QKeyEvent *)event;
……
return false;
}
return true;
}
true表示accept,事件终止,false表示ignore,事件继续传播。
3、在QObject安装上事件过滤器
lineEdit->installEventFilter(this);
bool Dialog::eventFilter(QObject *target, QEvent *event)
{
if (target == lineEdit) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast(event);
if (keyEvent->key() == Qt::Key_Space) {
……
return true;
}
}
}
return QDialog::eventFilter(target, event);
}
lineEdit->installEventFilter(this);
bool Dialog::eventFilter(QObject *target, QEvent *event)
{
if (target == lineEdit) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast(event);
if (keyEvent->key() == Qt::Key_Space) {
……
return true;
}
}
}
return QDialog::eventFilter(target, event);
}
4、在aApp上安装一个事件过滤器
这个过滤器会监视程序中发送到所有对象的所有事件,示例和为QObject类似。
5、重新实现QApplication:notify()
bool MyEvent::notify(QObject *target, QEvent *event)
{
if(event->type() == MyEventType)
{
……
return true;
}
return QCoreApplication::notify(target,event);
}