• 【QT】事件分发器/事件过滤器/事件处理的介绍和使用


    事件分发函数 event()

    在这里插入图片描述

    事件分发器:返回值 bool

    如果返回时true,代表用户要处理事件,不再分发事件了。

    • 事件对象创建完毕后,Qt 将这个事件对象传递给QObject的event()函数。
    • event()函数并不直接处理事件,而是将这些事件对象按照它们不同的类型,分发给不同的事件处理(eventhandler)。

    因此如上所述,event()函数主要用于事件的分发。所以,如果你希望在事件分发之前做一些操作,就可以重写这个event()函数了。

    event事件

    #include 
    
    • 1
    • 用途:用于事件的分发
    • 也可以用作拦截事件(不建议)

    例如,我们希望在一个QWidget组件中监听 tab 键的按下,那么就可以继承QWidget,并重写它的event()函数,来达到这个目的

    在这里插入图片描述

    //事件分发器
    bool mylabel::event(QEvent *e)
    {    
    if(e->type() == QEvent::KeyPress)
        {
           静态类型转换
            QKeyEvent *keyEvent = static_cast<QKeyEvent*>(e);
            if(keyEvent->key()==Qt::Key_Tab)
            {
                qDebug()<<"tab had pressed";
                return true;
            }
        }
        return QWidget::event(e);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    做一个拦截的目的时,说明它可以做拦截。

    实际应用就是鼠标事件就用鼠标相应的函数操作,定时器就用定时器。

    
    //事件分发器
    bool mylabel::event(QEvent *e)
    {
     //如果键盘按下,在event事件分发中做拦截操作
        if(e->type() == QEvent::MouseButtonPress)
        {
            //静态类型转换
             QMouseEvent *ev = static_cast<QMouseEvent*>(e);
             QString str = QString("Event函数中,鼠标按下了 x = %1,y=%2 globalX =%3 globalY = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
             qDebug()<<str;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    //会做类型检查,相对安全,但是带来的成本高于static_cast

     QMouseEvent *ev  = dynamic_cast<QMouseEvent*>(e);//会做类型检查,相对安全,但是带来的成本高于static_cast
    
    • 1

    事件过滤器(了解即可)

    1. 事件过滤器可以对需要的组件接收到的事件进行过滤,以及监控
    2. 任意的QObject对象都可以作为事件过滤器使用
    3. 事件过滤器的实现,需要重写eventFilter()函数
    4. 组件要想被监控,则需要通过installEventFilter()安装事件过滤器
    5. 事件过滤器能够决定是否将事件转发给组件对象,如下图所示:

    在这里插入图片描述

    obj->installEventFilter(filterObject);常常是obj->installEventFilter(this).

    • 发送到obj的所有事件, 都会先发送到filterObject的eventFilter()方法,
    • 即filterObject会过滤obj的事件, 这样就不用为了实现一个事件而要去继承, 再实现一个类, 完成如mouse event, key event等了, 只用在当前类中就可以通过事件过滤来完成.

    在这里插入图片描述

    在程序将事件分发到事件分发器前,可以利用过滤器拦截

    1.给控件安装事件过滤器

    2.重写eventFilter函数(obj,sv)

    public:
        explicit Event(QWidget *parent = nullptr);
        ~Event();
        //重写事件过滤器事件
        bool eventFilter(QObject*obj,QEvent*e);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    #include "event.h"
    #include "ui_event.h"
    #include 
    #include 
    #include 
    Event::Event(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Event)
    {
        ui->setupUi(this);
        //步骤一安装事件过滤器
        ui->label->installEventFilter(this);
        //步骤2L重写eventfilter事件
    }
    
     bool Event::eventFilter(QObject*obj,QEvent*e)
     {
         if(obj == ui->label)
         {
         if(e->type() == QEvent::MouseButtonPress)
         {
             //静态类型转换
              QMouseEvent *ev  = dynamic_cast<QMouseEvent*>(e);//会做类型检查,相对安全,但是带来的成本高于static_cast
             //QMouseEvent *ev = static_cast(e);
              QString str = QString("EventFilter函数中,鼠标按下了 x = %1,y=%2 globalX =%3 globalY = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
              qDebug()<<str;
          }
         }
         //其他默认处理
         return QWidget::eventFilter(obj,e);
     }
    Event::~Event()
    {
        delete ui;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    在这里插入图片描述

    Qt事件处理介绍

    • Qt平台会将系统产生的消息转换为Qt事件
    • Qt事件是一个QEvent的对象
    • Qt事件用来描述程序内部或外部发生的动作
    • 任意的QObject对象都具备事件处理的能力

    如下图所示,可以看到QEvent的子类非常之多:

    在这里插入图片描述

    • **QInputEvent:**用户输入事件
    • **QDropEvent:**用户拖放事件
    • **QPaintEvent:**描述操作系统绘制GUI动作的事件
    • **QCloseEvent:**用户关闭窗口事件
    • **QTimerEvent:**计时器事件

    事件处理方式顺序

    1.Qt事件产生后立即被分发到QWidget对象

    2.QWidget中的**event(QEvent*)**进行事件处理

    3.event()根据事件类型调用不同的事件处理函数

    4.在事件处理函数中发送Qt中预定义的信号

    5.调用信号关联的槽函数

    举个例子:

    1.当点击按钮后,将会触发**鼠标事件,调用event(QEvent*)**成员函数

    3.调用**mouseReleaseEvent(QMouseEvent*)**成员函数

    4.调用**click()**成员函数

    5.触发信号SIGNAL(clicked());

    同样,当用户点击窗口的关闭按钮时,也会触发closeEvent()事件函数,该函数需要重写,才能实现

     void MainWindow::closeEvent(QCloseEvent *event)
    {
         if (maybeSave())                        //如果还有需要保存的数据
        {
             writeSettings();
             event->accept();
        } 
         else                                    //取消关闭窗口
        {
             event->ignore();
        }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    类似的还有**keyEvent()**获取键盘事件函数, **keyReleaseEvent()**键盘按下事件函数,enterEvent光标进入组件事件函数, leaveEvent光标离开组件事件函数等等。

    其中QCloseEvent继承与QEvent,在QEvent中常用成员函数有

    void  accept ();    //接收者处理当前事件
    
    void  ignore ();    //接收者忽略当前事件,忽略后,事件可能传递给父组件
    
    bool isAccepted();  //判断当前事件是否被
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    通讯录(C语言版)
    Webapp中完成资源的跳转:转发和重定向
    Jmeter获取Websocket多帧消息的实现方法
    数据模型设计方法概述
    Linux 硬盘存储和文件系统介绍
    【vue.js】路由使用与Node.js下载安装之环境配置
    我的驾照考试笔记(2)
    mybatis动态sql和分页
    C# 图解教程 第5版 —— 第6章 方法
    【机器学习】机器学习创建算法第2篇:K-近邻算法【附代码文档】
  • 原文地址:https://blog.csdn.net/weixin_52958292/article/details/136529709