当前位置:首页 » 《我的小黑屋》 » 正文

【QT】事件分发器 & 事件过滤器

24 人参与  2025年01月01日 10:01  分类 : 《我的小黑屋》  评论

点击全文阅读


qt 系统 - 事件分发器 and 事件过滤器

一、事件分发器1. 事件分发器概念2. 事件分发器工作原理 二、事件过滤器

一、事件分发器

1. 事件分发器概念

在 Qt 中,事件分发器(Event Dispatcher) 是一个核心概念,用于处理 GUI 应用程序中的事件。事件分发器负责将事件从⼀个对象传递到另⼀个对象,直到事件被处理或被取消。每个继承自 QObject 类或 QObject 类本身都可以在本类中重写 bool event(QEvent *e) 函数,来实现相关事件的捕获和拦截。

2. 事件分发器工作原理

在 Qt 中,我们发送的事件都是传给了 QObject 对象,更具体点是传给了 QObject 对象的 event() 函数。所有的事件都会进入到这个函数里面,那么我们处理事件就要重写这个 event() 函数。event() 函数本⾝不会去处理事件,而是根据 事件类型(type值)调用不同的事件处理函数。事件分发器就是工
作在应用程序向下分发事件的过程中,如下图:

在这里插入图片描述

如上图,事件分发器⽤于分发事件。在此过程中,事件分发器也可以做拦截操作。事件分发器主要是通过 bool event(QEvent *e) 函数来实现。其返回值为布尔类型,若为 ture,代表拦截,不向下分发。

Qt 中的事件是封装在 QEvent 类中,在 Qt 助手中输入 QEvent 可以查看其所包括的事件类型,如下图示:

在这里插入图片描述

在这里插入图片描述

示例代码:

1、在 “widget.h” 头⽂件中声明 ⿏标点击事件 和 事件分发器;如下图⽰:

class Widget : public QWidget{    Q_OBJECTpublic:    Widget(QWidget *parent = nullptr);    ~Widget();    // 鼠标点击事件    void mousePressEvent(QMouseEvent* event);    // 通过事件分发器拦截鼠标按下事件    bool event(QEvent* event);private:    Ui::Widget *ui;};

2、在 “widget.cpp” ⽂件中实现 ⿏标点击事件 和 拦截事件;

#include <QDebug>#include <QMouseEvent>void Widget::mousePressEvent(QMouseEvent *event){    if(event->button() == Qt::LeftButton) {        qDebug() << "鼠标左键被按下!";    }}bool Widget::event(QEvent *event){    if(event->type() == QEvent::MouseButtonPress) {        qDebug() << "Event 中鼠标被按下!";        return true; // return true 代表不向下分发    }    // 其它事件交给父类处理(默认处理)    return false;}

执行效果如下,当鼠标左键点击窗口时,就会执行 event 函数,而不会执行 mousePressEvent 函数:

在这里插入图片描述

二、事件过滤器

在 Qt 中,⼀个对象可能经常要查看或拦截另外⼀个对象的事件,如对话框想要拦截按键事件,不让别的组件接收到,或者修改按键的默认值等。通过上面的学习,我们已经知道,Qt 创建了 QEvent 事件对象之后,会调用 QObjectevent() 函数处理事件的分发。显然,我们可以在 event() 函数 中实现拦
截的操作。由于 event() 函数是 protected 的,因此,需要继承已有类。如果组件很多,就需要重写很多个 event() 函数。这当然相当麻烦,更不用说重写 event() 函数还得小心一堆问题。好在 Qt 提供了另外⼀种机制来达到这一目的:事件过滤器

事件过滤器是在应用程序分发到 event 事件分发器之前,再做⼀次更高级的拦截。如下图示:

在这里插入图片描述

事件过滤器的⼀般使用步骤:

安装事件过滤器;重写事件过滤器函数:eventfilter()

代码示例:

1、设计 UI 文件,拖入一个 label,如下图示;

在这里插入图片描述

3、在项目新添加⼀个类:MyLabel

先选中项目名称 QEvent_2,点击⿏标右键,选择 add new … ,弹出如下对话框,选择 Choose 即可:

在这里插入图片描述

4、选择:Choose … 后,弹出如下界面,按照如下形式创建即可:

在这里插入图片描述

5、此时项目中会新添加我们刚新建的头文件和cpp文件;
6、在 UI 文件中选中 Label,右键 ------> 提升为…;当点击 "提升为… " 之后,弹出如下对话框:

在这里插入图片描述

接下来按照下图选择即可:

在这里插入图片描述

7、在 “mylabel.h” 中声明 ⿏标点击事件 和 事件分发器:

#include <QWidget>#include <QLabel>class myLabel : public QLabel{    Q_OBJECTpublic:    explicit myLabel(QWidget *parent = nullptr);        // 鼠标点击事件    void mousePressEvent(QMouseEvent* event);        // 事件分发器    bool event(QEvent* e);};

8、在 “mylabel.cpp” ⽂件中实现⿏标点击事件和事件分发器;

#include <QMouseEvent>#include <QDebug>myLabel::myLabel(QWidget *parent) : QLabel(parent){}void myLabel::mousePressEvent(QMouseEvent *event){    QString str = QString("鼠标按下: x = %1, y = %2").arg(event->x()).arg(event->y());    qDebug() << str.toUtf8().data();}bool myLabel::event(QEvent *e){    // 如果是鼠标按下,在event事件分发时拦截操作    if(e->type() == QEvent::MouseButtonPress) {        QMouseEvent* event = static_cast<QMouseEvent*>(e);        QString str = QString("Event 函数中鼠标按下: x = %1, y = %2").arg(event->x()).arg(event->y());        qDebug() << str.toUtf8().data();        return true; // 返回true,代表用户自己处理,不向下分发    }    return QLabel::event(e); // 其他事件交给父类处理}

9、在 “widget.h” 头文件中声明事件过滤器函数;

class Widget : public QWidget{    Q_OBJECTpublic:    Widget(QWidget *parent = nullptr);    ~Widget();        // 声明 eventfilter 事件    bool eventFilter(QObject* obj, QEvent* e);private:    Ui::Widget *ui;};

10、在 “widget.cpp” ⽂件中实现事件过滤器的两个步骤;

#include <QEvent>#include <QMouseEvent>#include <QDebug>Widget::Widget(QWidget *parent)    : QWidget(parent)    , ui(new Ui::Widget){    ui->setupUi(this);        // 1. 给label安装事件过滤器,this:当前窗口安装事件过滤器    ui->label->installEventFilter(this);}// 2. 重写eventfilter事件bool Widget::eventFilter(QObject *obj, QEvent *e){    // 判断控件    if(obj == ui->label) {        if(e->type() == QEvent::MouseButtonPress) {            QMouseEvent* event = static_cast<QMouseEvent*>(e);            QString str = QString("事件过滤器中鼠标按下:x = %1, y = %2").arg(event->x()).arg(event->y());            qDebug() << str.toUtf8().data();                        return true;        }    }    // 其它交给父类处理    return QWidget::eventFilter(obj, e);}

执行效果如下,当在标签中点击鼠标时不会执行 event 函数,而会执行 eventfilter 函数:

在这里插入图片描述


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/210114.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1