39、拓展知识---------事件系统

拓展知识

1 多层级事件过滤

事件过滤器不仅可以安装在目标对象上,也可以安装在父对象或更高层级的对象上。这样可以实现全局或局部的事件监控和处理。

为了方便,我们在MainWindow.h中定义一个ClickEventFilter类,实现eventFilter捕获KeyPress按键事件

cpp 复制代码
class ClickEventFilter : public QObject
{
    Q_OBJECT
public:
    explicit ClickEventFilter(QObject *parent = nullptr) : QObject(parent) {}

protected:
    bool eventFilter(QObject *obj, QEvent *event) override {
        //如果是按键事件
        if (event->type() == QEvent::KeyPress) {
            //转化为按键事件
            QKeyEvent * key_event= static_cast<QKeyEvent*>(event);
            //获取对象名称
            QString objectName = obj->objectName();

            if (objectName.isEmpty()) {
                objectName = obj->metaObject()->className();
            }

            QMessageBox::information(nullptr, "Global Click Filter",
                                     QString("Pressed object: %1\n Key Text is %2\n")
                                     .arg(objectName)
                                     .arg(key_event->text()));
            // 返回 false 以允许事件继续传递
            return false;
        }
        return QObject::eventFilter(obj, event);
    }
};

我们在mainwindow中创建一个按钮

cpp 复制代码
auto *pushBtn = new QPushButton("click me", this);
pushBtn->setGeometry(100,100,100,50);

接下来我们在main.cpp中为Application安装这个事件过滤器, 因为Application位于最顶层,所以事件过滤器安装在了最顶层,那么可以监控所有对象的事件

cpp 复制代码
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    ClickEventFilter *filter = new ClickEventFilter(&a);
    a.installEventFilter(filter);

    return a.exec();
}

我们运行程序后,点击按键d,会发现依次弹出三个对话框,表明我们为最顶层app安装了过滤器达到了监听所有对象的效果。

先弹出最顶层窗口MainWindowWindow的按键消息

再弹出按钮的按键消息

最后弹出MainWindow的按键消息

2 多事件过滤器优先级

一个对象可以安装不同的事件过滤器,假设我们为按钮安装了两个事件过滤器,一个高优先级的事件过滤器内部返回true,就会阻止低优先级的事件过滤器处理。

我们先实现两个等级的事件过滤器

cpp 复制代码
//高优先级过滤器
class HighPriorityFilter : public QObject
{
    Q_OBJECT
public:
 explicit HighPriorityFilter(QObject *parent = nullptr) : QObject(parent) {}
protected:
    bool eventFilter(QObject *obj, QEvent *event) override
    {
        //判断鼠标事件
        if (event->type() == QEvent::MouseButtonPress) {
            QMessageBox::information(nullptr, "High Priority Filter",
                                     "High priority filter intercepted the click!");
            // 阻止事件继续传递
            return true;
        }
        return QObject::eventFilter(obj, event);
    }
};

//低优先级事件过滤器
class LowPriorityFilter : public QObject
{
    Q_OBJECT
public:
 explicit LowPriorityFilter(QObject *parent = nullptr) : QObject(parent) {}
protected:
    bool eventFilter(QObject *obj, QEvent *event) override
    {
        //鼠标按下事件
        if (event->type() == QEvent::MouseButtonPress) {
            QMessageBox::information(nullptr, "Low Priority Filter",
                                     "Low priority filter intercepted the click!");
            // 允许事件继续传递
        }
        return QObject::eventFilter(obj, event);
    }
};

接下来我们在MainWindow的构造函数里创建按钮,并为它安装这两个过滤器,最后安装的最先触发

cpp 复制代码
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    auto *pushBtn = new QPushButton("click me", this);
    pushBtn->setGeometry(100,100,100,50);
    //注意安装顺序,最后安装的被认为是最先触发的
    auto * low_filter = new LowPriorityFilter(pushBtn);
    pushBtn->installEventFilter(low_filter);
    //最后安装的最先触发,被认为是高级事件过滤器
    auto * high_filter = new HighPriorityFilter(pushBtn);
    pushBtn->installEventFilter(high_filter);
}

运行程序,点击按钮,会发现只弹出高级事件过滤器的消息框

如果我们将HighPriorityFiltereventFilter内部的逻辑改为返回false,就表示这个事件过滤器未完全处理好这个事件,可以继续交给其他事件过滤器处理

我们点击按钮后,会先弹出High priority filter,再弹出下面的消息框

相关推荐
江屿风几秒前
C++OJ题经验总结(竞赛)1
开发语言·c++·笔记·算法
运筹vivo@20 分钟前
LeetCode 2405. 子字符串的最优划分
c++·算法·leetcode·职场和发展·哈希表
有点。1 小时前
C++(枚举法一练习题)
开发语言·c++·算法
basketball6161 小时前
C++ 单例模式完全指南:从饿汉式到现代 C++ 的最佳实践
java·c++·单例模式
AoDeLuo1 小时前
SOEM2.0编译与Qt调用
qt·机器视觉
玖釉-1 小时前
栈——栈的定义及基本操作
c++·windows·算法·图形渲染
不想写代码的星星2 小时前
C++ 内存序六件套:从完全同步到爱咋咋地
c++
大树学长2 小时前
【QT开发】Windows 10 + Qt 5.15.2 手动编译安装 Qt OPC UA 模块完整记录
开发语言·windows·qt
haibindev3 小时前
别让AI再从零写一堆优美的屎山了
c++·ai编程·claude·流媒体·codex·代码复用