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,再弹出下面的消息框

相关推荐
无限进步_7 分钟前
【C++】巧用静态变量与构造函数:一种非常规的求和实现
开发语言·c++·git·算法·leetcode·github·visual studio
小超超爱学习993724 分钟前
大数乘法,超级简单模板
开发语言·c++·算法
knighthood200132 分钟前
Qt5.15+VTK9.3.0实现点云点选功能
开发语言·qt
xyx-3v2 小时前
qt创建新工程
开发语言·c++·qt
样例过了就是过了2 小时前
LeetCode热题100 爬楼梯
c++·算法·leetcode·动态规划
少司府2 小时前
C++基础入门:类和对象(中)
c语言·开发语言·c++·类和对象·运算符重载·默认成员函数
王老师青少年编程2 小时前
csp信奥赛c++之状压枚举
数据结构·c++·算法·csp·信奥赛·csp-s·状压枚举
大神的风范3 小时前
QT部署YOLO11实时检测
驱动开发·深度学习·qt·目标检测·计算机视觉
cpp_learner3 小时前
Linux ARM架构 使用 linuxdeployqt 打包QT程序
qt
泉飒3 小时前
C2001: 常量中有换行符-QT解决办法-逆向思路
开发语言·qt