【Qt笔记】event()

前面的章节中咱们曾经提到event()函数。事件对象建立完毕后,Qt 将这个事件对象传递给QObjectevent()函数。event()函数并不直接处理事件,而是将这些事件对象按照它们不一样的类型,分发给不一样的事件处理器(event handler)。函数

 

如上所述,event()函数主要用于事件的分发。因此,若是你但愿在事件分发以前作一些操做,就能够重写这个event()函数了。例如,咱们但愿在一个QWidget组件中监听 tab 键的按下,那么就能够继承QWidget,并重写它的event()函数,来达到这个目的:测试

bool CustomWidget::event(QEvent *e)
{
    if (e->type() == QEvent::KeyPress) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(e);
        if (keyEvent->key() == Qt::Key_Tab) {
            qDebug() << "You press tab.";
            return true;
        }
    }
    return QWidget::event(e);
}

CustomWidget是一个普通的QWidget子类。咱们重写了它的event()函数,这个函数有一个QEvent对象做为参数,也就是须要转发的事件对象。函数返回值是 bool 类型。若是传入的事件已被识别而且处理,则须要返回 true,不然返回 false。若是返回值是 true,而且,该事件对象设置了accept(),那么 Qt 会认为这个事件已经处理完毕,不会再将这个事件发送给其它对象,而是会继续处理事件队列中的下一事件。注意,在event()函数中,调用事件对象的accept()ignore()函数是没有做用的,不会影响到事件的传播。code

咱们能够经过使用QEvent::type()函数能够检查事件的实际类型,其返回值是QEvent::Type类型的枚举。咱们处理过本身感兴趣的事件以后,能够直接返回 true,表示咱们已经对此事件进行了处理;对于其它咱们不关心的事件,则须要调用父类的event()函数继续转发,不然这个组件就只能处理咱们定义的事件了。为了测试这一种状况,咱们能够尝试下面的代码:对象

bool CustomTextEdit::event(QEvent *e)
{
    if (e->type() == QEvent::KeyPress) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(e);
        if (keyEvent->key() == Qt::Key_Tab) {
            qDebug() << "You press tab.";
            return true;
        }
    }
    return false;
}

CustomTextEditQTextEdit的一个子类。咱们重写了其event()函数,却没有调用父类的同名函数。这样,咱们的组件就只能处理 Tab 键,再也没法输入任何文本,也不能响应其它事件,好比鼠标点击以后也不会有光标出现。这是由于咱们只处理的KeyPress类型的事件,而且若是不是KeyPress事件,则直接返回 false,鼠标事件根本不会被转发,也就没有了鼠标事件。继承

经过查看QObject::event()的实现,咱们能够理解,event()函数同前面的章节中咱们所说的事件处理器有什么联系:队列

//!!! Qt5
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;
}

这是 Qt 5 中QObject::event()函数的源代码(Qt 4 的版本也是相似的)。咱们能够看到,同前面咱们所说的同样,Qt 也是使用QEvent::type()判断事件类型,而后调用了特定的事件处理器。好比,若是event->type()返回值是QEvent::Timer,则调用timerEvent()函数。能够想象,QWidget::event()中必定会有以下的代码:事件

switch (event->type()) {
    case QEvent::MouseMove:
        mouseMoveEvent((QMouseEvent*)event);
        break;
    // ...
}

事实也的确如此。timerEvent()mouseMoveEvent()这样的函数,就是咱们前面章节所说的事件处理器 event handler。也就是说,event()函数中实际是经过事件处理器来响应一个具体的事件。这至关于event()函数将具体事件的处理“委托”给具体的事件处理器。而这些事件处理器是 protected virtual 的,所以,咱们重写了某一个事件处理器,便可让 Qt 调用咱们本身实现的版本。get

由此能够见,event()是一个集中处理不一样类型的事件的地方。若是你不想重写一大堆事件处理器,就能够重写这个event()函数,经过QEvent::type()判断不一样的事件。鉴于重写event()函数须要十分当心注意父类的同名函数的调用,一不留神就可能出现问题,因此通常仍是建议只重写事件处理器(固然,也必须记得是否是应该调用父类的同名处理器)。这其实暗示了event()函数的另一个做用:屏蔽掉某些不须要的事件处理器。正如咱们前面的CustomTextEdit例子看到的那样,咱们建立了一个只能响应 tab 键的组件。这种做用是重写事件处理器所不能实现的。it

相关文章
相关标签/搜索