QT重载事件处理器
QEvent类是所有事件类的基类,事件类包含事件参数。
Qt的主事件回路(QApplication::exec())从事件队列里取得本地窗口系统事件,并把它们转换为QEvent并且把这些转换过的事件发给QObject。
具体QT是如何获取和分发事件的,参考:
http://blog.csdn.net/changsheng230/article/details/6085080
http://blog.csdn.net/changsheng230/article/details/6092978
通常情况下,来自于窗口系统的事件(spontaneous()返回真),但是它也可以使用QApplication::sendEvent()和QApplication::postEvent()手动发送事件(spontaneous()返回假)。
QObject通过它们的QObject::event()函数调用来接收事件。这个函数可以在子类中重新实现来处理自定义的事件和添加额外的事件类型,QWidget::event()就是一个著名的例子。默认情况下,像QObject::timerEvent()和QWidget::mouseMoveEvent()这样的事件可以被发送给事件处理函数。QObject::installEventFilter()允许一个对象中途截取发往另一个对象的事件。
基本的QEvent只包含了一个事件类型参数。QEvent的子类包含了额外的描述特定事件的参数。
也可以参考QObject::event()、QObject::installEventFilter()、QWidget::event()、QApplication::sendEvent()、QApplication::postEvent()、QApplication::processEvents()、EnvironmentClasses和事件类。
这里先讨论一种简单的方法,就是重新实现事件处理器达到自己想要的目的:
Qt中有这么多类的事件,我们怎么样比较简便的处理每个事件呢?设想,如果是每个事件都对应同一个事件处理器,在该事件处理器中对不同的事件进行分类处理,这样的弊端有两点:第一,导致该事件处理器过于臃肿复杂;第二,这样不便于扩展,当系统新增加事件类型或者是我们需要使用到自定义事件时,就不得不修改Qt的源码来达到目的。所以Qt设计者的做法是针对不同类型的事件提供不同的事件处理器与之对应。这里又有一个问题了,Qt中是怎么让不同类型事件与之对应的事件处理器相关联的呢?我们不难猜想在事件和事件处理器中间必定有一个桥梁。这个桥梁就是QObject::event()函数,该函数是虚函数,QObject的子类例如QWidget都实现了该函数。该函数的主要功能是进行事件的分发,也就是将不同类型的事件与之相对应的事件处理器相关联,该函数并不对事件进行处理,真正的事件处理是在事件处理器中进行的。
例如:当QWidget产生QPaintEvent事件后,QWidget的event函数会将该事件分发给QWidget::paintEvent()事件处理器,这样该事件就得到处理了。
以上内容用一个图形表示就是:
根据需要,我们可以重载event()函数,在event()里加入事件的处理,也可以重载事件处理器函数,如:QResizeEvent,QPaintEvent,QMouseEvent,QKeyEvent和QCloseEvent。
(1)重载event()函数
例如在event()函数里实现“Tab”键的缩进功能。
bool mywidget::event(QEvent *event)
{
if(event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = stadic_cast<QKeyEvent *>(event);
if(keyEvent->key() == Qt::Key_Tab )
{
insertCurrentPosition('\t');
return true;
}
}
return QWidget::event(event); //这一句是将其他事件传递给它的父窗口部件来处理
}
(2)重载事件处理函数
让我们试着设想已经有了一个CustomerInfoDialog的小部件。CustomerInfoDialog 包含一系列QLineEdit. 现在,我们想用空格键来代替Tab,使焦点在这些QLineEdit间切换。
一个解决的方法是子类化QLineEdit,重新实现keyPressEvent(),并在keyPressEvent()里调用focusNextChild()。像下面这样:
void MyLineEdit::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Space) {
focusNextChild();
} else {
QLineEdit::keyPressEvent(event); //返回其他未处理事件
}
}