事件传递机制

eventfilter(事件过滤器也可以自己观察自己)

// 无论是true 或者 false 事件处理函数都需要手动调用,否则不进
B->installeventfilter(A);         // A控制B
// 事件过滤器的参数类中需要实现eventfilter函数,A->eventfilter();
bool eventfilter(QObject*, QEvent*)
{
	return true;  // 不继续向父组件传递
	return false;  // 继续向父组件传递
	return FU::eventfilter(..., ...);  //使用父类的处理方式
}

多次进事件过滤的情况

// 会进三次第二层if
bool tabHistogram::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == ui->lineEdit_left || watched == ui->lineEdit_right ||
        watched == ui->lineEdit_decomposel || watched == ui->lineEdit_decomposer) {
            QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
            if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
                if(watched == ui->lineEdit_left) {
                    on_lineEdit_left_editingFinished();
                } else if(watched == ui->lineEdit_right) {
                    on_lineEdit_right_editingFinished();
                }else if(watched == ui->lineEdit_decomposel) {
                    on_lineEdit_decomposel_editingFinished();
                } else if(watched == ui->lineEdit_decomposer) {
                    on_lineEdit_decomposer_editingFinished();
                }
                return true;
    }

    return QWidget::eventFilter(watched, event);
}

✅ 回车键会触发的几个常见事件(一次回车 ≠ 一个事件) 当你按一下回车(Enter)键时,Qt 会依次生成如下事件序列: | 事件类型 | 含义 | | ————————– | ——————— | | QEvent::KeyPress | 键盘按下(你监听的事件) | | QEvent::ShortcutOverride | 如果系统中定义了快捷键,先让它们有机会处理 | | QEvent::KeyRelease | 键盘释放 |

你看到的现象 原因说明
回车触发三次事件 Qt 会发出多种事件(Press、Release)
eventFilter 进三次 是所有事件都经过 eventFilter
判断条件只命中一次 只有 KeyPress 分支会触发处理逻辑
bool tabHistogram::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == ui->lineEdit_left || watched == ui->lineEdit_right ||
        watched == ui->lineEdit_decomposel || watched == ui->lineEdit_decomposer) {
        if (event->type() == QEvent::KeyPress) {
            QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
            if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
                if(watched == ui->lineEdit_left) {
                    on_lineEdit_left_editingFinished();
                } else if(watched == ui->lineEdit_right) {
                    on_lineEdit_right_editingFinished();
                }else if(watched == ui->lineEdit_decomposel) {
                    on_lineEdit_decomposel_editingFinished();
                } else if(watched == ui->lineEdit_decomposer) {
                    on_lineEdit_decomposer_editingFinished();
                }
                return true;
            }
        }
    }

    return QWidget::eventFilter(watched, event);
}

专门的事件过滤类

class MyFilter : public QObject
{
    Q_OBJECT
protected:
    bool eventFilter(QObject* obj, QEvent* event) override
    {
        if (event->type() == QEvent::MouseButtonPress)
        {
            qDebug() << "Mouse press intercepted on object:" << obj;
            return true; // 阻止事件继续传递
        }
        return QObject::eventFilter(obj, event); // 不拦截,继续传递
    }
};

// 使用
MyFilter* filter = new MyFilter();
targetWidget->installEventFilter(filter);

事件循环机制

事件的传递顺序是 事件过滤器 ——> 事件分发 ——> 事件处理函数

事件过滤器中如果返回值是false,表示传递给对应的对象处理。如果返回的是true,表示不继续传递给其它事件过滤器,并且终止。最后调用父类的事件过滤函数。实际测试事件过滤器中也支持ignore和accept方法

事件分发 中需要调用事件处理函数才会走处理函数, 如果返回的是false, 表示继续传递给父组件, 如果返回的是true, 表示就此终止,函数末尾需要再调用父类的event方法。

事件处理函数是事件的最后一步。accept——不再继续向父组件发送;ignore——继续向父组件发送;事件处理函数默认是accept,QWidget的方法则默认是ignore.

QEvent中return的返回值是和notify()通信,而accept和ignore是和具体的事件函数通信。

QEvent的返回值是true表示用户自己处理这个事件。并且如果是event->ignore(),就算调用true,也会向父控件传递消息。如果是accept,就算是false,也会向父控件传递消息。其实ignore和accept最好只在事件处理函数中出现。

test:

控件A包含控件B,B包含控件C,C包含button D。A/B/C中有事件过滤器,事件分发器,都返回false。D中有event,返回false。点击D,分别打印,C事件过滤器,D事件分发器,B事件过滤器,C事件分发器,A事件过滤器,B事件分发器。

加入NativeEvent

 ┌──────────────┐
 │ Win32事件(如WM_MOUSEMOVE) │
 └──────────────┘
         ↓
 ┌──────────────┐
 │ nativeEvent()│ ← 只有顶层窗口才会收到
 └──────────────┘
         ↓
 ┌──────────────────────────┐
 │ Qt 内部生成 QEvent 对象   │ ← 例如 QMouseEvent
 └──────────────────────────┘
         ↓
 ┌──────────────┐
 │ eventFilter()│ ← 安装者优先收到,能阻断传递
 └──────────────┘
         ↓
 ┌────────────┐
 │ event()    │ ← 主处理函数
 └────────────┘
         ↓
 ┌─────────────────────┐
 │ mousePressEvent() 等 │ ← 特化处理函数
 └─────────────────────┘
Table of Contents