在Qt中,event()函数是所有事件进入一个对象的总入口。它本身不直接处理事件,而是像一个 “总调度员”,负责把特定类型的事件(如鼠标点击、键盘按键)分发给对应的事件处理器(如 mousePressEvent,keyPressEvent

  • 事件分发:
    这是它的首要职责。根据 QEvent::type() 判断事件类型,然后调用对应的具体事件处理函数。
  • 提前拦截或替换处理:
    在事件被分发给具体处理器之前,你可以重写这个函数来执行一些前置操作,甚至完全接管某个事件的处理。

可以通过查看Qt源码验证,在qwidget.cppevent()事件分发函数中,通过区分不同的事件类型来调用特定的事件处理函数
也就是说,可以在事件到达默认的事件处理函数之前,在event()中截获

bool QWidget::event(QEvent *event)
{
    switch (event->type()) {
  
        case QEvent::MouseMove:
            mouseMoveEvent((QMouseEvent*)event);
            break;
        case QEvent::MouseButtonPress:
            mousePressEvent((QMouseEvent*)event);
            break;
        case QEvent::MouseButtonRelease:
            mouseReleaseEvent((QMouseEvent*)event);
            break;
        case QEvent::MouseButtonDblClick:
            mouseDoubleClickEvent((QMouseEvent*)event);
            break;
        case QEvent::Drop:
            dropEvent((QDropEvent*) event);
            break;
        case QEvent::DragEnter:
            dragEnterEvent((QDragEnterEvent*) event);
            break;
        case QEvent::DragMove:
            dragMoveEvent((QDragMoveEvent*) event);
            break;
        case QEvent::DragLeave:
            dragLeaveEvent((QDragLeaveEvent*) event);
            break;
        default:
            return QObject::event(event);
    }
    return true;
}

1. 重写 event() 函数

首先,在 labelpropagate.h 中,声明event()事件分发函数,如下:

class LabelPropagate : public QLabel {
protected:
    bool event(QEvent *e);
};

然后,在labelpropagate.cpp 中,实现event()函数,如下:

// 最后调用了父类的 event() 函数,父类的 event() 函数的作用就是接着把事件分发到特定的事件处理函数。
// 如果直接返回 true 或 false 而不调用父类的 event() 函数,则无法将事件传递给特定的事件处理函数!
bool LabelPropagate::event(QEvent *e)
{
    if (e->type() == QEvent::MouseButtonPress) {
        qDebug() << "LabelPropagate::event()";
    }

    return QLabel::event(e);  // 调用父类的 event() 函数
}

此时,运行效果:
image-20260820124607305

此时的事件传递流程:
(1)事件首先到达LabelPropagate中的event()函数
(2)上一步的event()函数,调用了父类的event()函数,因此事件被分发到PropagateLabel中的mouseMoveEvent()函数
(3)PropagateLabel中的mouseMoveEvent()函数,忽略了该事件,因此事件又被传递到PropagateWidget中的 mouseMoveevent()函数

2. event() 的返回值

事件分发函数event()返回一个bool值,通常直接调用父类的event()事件分发函数,这样可以接着把事件分发到特定的事件处理函数
那么:如果不调用父类的event()函数,而是直接返回true或者false,会有什么效果呢?

// 这里对于 QEvent::MouseButtonPress 事件,
// 1. 直接返回 true
//     表示事件被识别,传递到此为止,不会接着传递。
//     此时运行,控制台打印如下:
//     LabelPropagate::event()
// 
// 2. 直接返回 false
//     表示事件没有被识别,会接着传递。
//     由于没有调用调用父类的 event() 函数,因此不会将事件分发到 LabelPropagate 的 mousePressEvent(),
//     而是直接传递给父控件的 mousePressEvent()
//     此时运行,控制台打印如下:
//     LabelPropagate::event()
//     PropagateWidget::mousePressEvent()

bool LabelPropagate::event(QEvent *e)
{
    if (e->type() == QEvent::MouseButtonPress) {
        qDebug() << "LabelPropagate::event()";
        // return true;
        return false;
    }

    return QLabel::event(e); 
}