Qt事件过滤器原理EventFilter(installEventFilter函数)

2023-11-12

Qt事件过滤器原理(installEventFilter函数)

本文为原创文章,转载请注明出处,或注明转载自“黄邦勇帅(原名:黄勇)

本文出自本人原创著作《Qt5.10 GUI完全参考手册》网盘地址:
https://pan.baidu.com/s/1iqagt4SEC8PUYx6t3ku39Q
《C++语法详解》网盘地址:https://pan.baidu.com/s/1dIxLMN5b91zpJN2sZv1MNg

若对C++语法不熟悉,建议参阅本人所著《C++语法详解》一书,电子工业出版社出版,该书语法示例短小精悍,对查阅C++知识点相当方便,并对语法原理进行了透彻、深入详细的讲解,可确保读者彻底弄懂C++的原理,彻底解惑C++,使其知其然更知其所以然。此书是一本全面了解C++不可多得的案头必备图书。

事件过滤器用于拦截传递到目标对象的事件,这样可以实现监视目标对象事件的作用。
1、Qt实现事件过滤器的步骤如下:
①、Qt调用
void QObject::installEventFilter (QObject* filterObj)
把filterObj对象安装(或注册)为事件过滤器,filterObj也称为过滤器对象。事件过滤器通常在构造函数中进行注册。
②、在上一步注册的filterObj对象,通过调用
bool QObject::eventFilter(QObject* obj, QEvent* e);
来接收拦截到的事件。也就是说拦截到的事件在filterObj对象中的eventFilter函数中处理。eventFilter的第一个参数obj指向的是事件本应传递到的目标对象。
③、使用QObject::removeEventFilter(QObject *obj)函数可以删除事件过滤器。
2、事件过滤器处理事件的规则
①、过滤器对象的eventFilter()函数可以接受或拒绝拦截到的事件,若该函数返回false,则表示事件需要作进一步处理,此时事件会被发送到目标对象本身进行处理(注意:这里并未向父对象进行传递),若evetnFilter()返回true,则表示停止处理该事件,此时目标对象和后面安装的事件过滤器就无法获得该事件。
②、若同一对象安装了多个事件过滤器,则最后安装的过滤器首先被激活。
3、为什么使用事件过滤器
使用事件过滤器可以简化程序代码。比如按钮1和标签1,对按下A键的事件响应相同的操作,若不使用事件过滤器,则需要分别子类化按钮和标签部件,并重新实现各自的事件处理函数。再如使用同一个子类化按钮的类C创建的按钮1和按钮2,对按下键A,按钮1和按钮2需要作不同的响应,若不使用事件过滤器,则他们的响应是相同的,若使用事件过滤器,则可以拦截按钮1或按钮2的事件并作特殊处理。
4、理解事件过滤器
观察者模式:其原理为,设有一目标对象S,它有多个观察该对象的对象G1,G2,G3,当S发生变化时,S的观察者会依情形改变自身。应用于Qt事件过滤器,则是,首先使用S的成员函数installEventFilter函数把G1,G2,G3设置为S的观察者,所有本应传递给S的事件E,则先传递给观察者G1,G2,G3,然后观察者调用其成员函数eventFilter对传递进来的事件进行处理,若eventFilter返回true表示事件处理完毕,返回false则返回给被观察者S进行处理。见图2-13。
在这里插入图片描述

示例2.22:事件过滤器的使用

#include <QApplication>
#include<QWidget>
#include<QMouseEvent>
#include<QPushButton>
#include<QObject>
#include <iostream>
using namespace std;
class A:public QObject{public:  //该类的对象用作过滤器对象,使用事件过滤器需继承QObject
bool eventFilter(QObject *w, QEvent *e){ 
if(e->type()==QEvent::MouseButtonPress)
            	{cout<<w->objectName().toStdString(); //验证w为事件本应到达的目标对象
                cout<<"=Ak"<<endl;
           		 return 1;  //返回1表示该事件不再进一步处理
            	}
                return 0;}  };  /*返回0表示其余事件交还给目标对象处理,本例应返回0,否则添加了该过滤器的安钮会无法显示。*/
class B:public A{public:   //继承自类A
bool eventFilter(QObject *w, QEvent *e){
if(e->type()==QEvent::MouseButtonPress){
cout<<w->objectName().toStdString()<<"=Bk"<<endl;
return 0;}
return 0;}	};
class C:public QWidget{public: void mousePressEvent(QMouseEvent *e){cout<<"Ck"<<endl;}};
class D:public QPushButton{public:void mousePressEvent(QMouseEvent *e){cout<<"DK"<<endl;}};

int main(int argc, char *argv[]){
QApplication a(argc,argv); 
//创建对象,注意:本例父对象应先创建,以避免生命期过早结束
    A ma;   	B mb;   	 C mc;   	 D *pd=new D;   	 D *pd1=new D;
    pd->setText("AAA");    pd->move(22,22);      pd1->setText("BBB");    pd1->move(99,22);
    //设置对象名
    ma.setObjectName("ma");   	mb.setObjectName("mb");   	mc.setObjectName("mc");
    pd->setObjectName("pd");   	pd1->setObjectName("pd1");
    //设置父对象
    pd->setParent(&mc);    pd1->setParent(&mc);
    mb.setParent(&ma);    //①
     //注册过滤器对象
    pd->installEventFilter(&mb);  //②
    pd1->installEventFilter(&ma); //③

mc.resize(333,222);    mc.show();    a.exec();    
return 0;     }
  • 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
  • 37
  • 38
  • 39
  • 40
  • 41

程序运行结果及说明(见图2-14)
在这里插入图片描述
当用鼠标按下按钮AAA时,输出pd=Bk和Dk。因为按钮AAA安装的过滤器对象为mb,因此由mb的eventFilter函数处理该事件,输出pd=BK,此时mb::eventFilter()返回0,表示此事件需作进一步处理,于是把该事件传递给目标对象处理(即pd所指向的对象),注意:本例虽然为mb设置了父对象ma,但事件并不会传递给父对象处理,而是返回给目标对象。此时调用D::mousePressEvent函数,输出Dk,至此事件处理结束。用鼠标按下按钮BBB输出pd1=Ak的原理略(较简单)
示例2.23:添加多个事件过滤器

#include <QApplication>
#include<QWidget>
#include<QMouseEvent>
#include<QPushButton>
#include<QObject>
#include <iostream>
using namespace std;
class A:public QObject{public:
        bool eventFilter(QObject *w, QEvent *e){
            if(e->type()==QEvent::MouseButtonPress)
          		{  cout<<"A"<<endl;
            			return 0;  }//此处应返回0,注意,返回1事件将停止传递。
             return 0;}		};
class B:public QObject{public:
        bool eventFilter(QObject *w, QEvent *e){
            if(e->type()==QEvent::MouseButtonPress){    cout<<"B"<<endl;return 0;  }
            return 0;} 		};
class C:public QObject{public:
        bool eventFilter(QObject *w, QEvent *e){
            static int i=0;
            if(e->type()==QEvent::MouseButtonPress){  cout<<"C="<<i++<<endl;return 0; }
            return 0;} 		};
int main(int argc, char *argv[]){ QApplication a(argc,argv); //Qt中QApplication类型的对象只能有一个
    //创建对象
    A ma;   B mb;    C mc,mc1;    //事件过滤器对象
    QWidget w;    QPushButton *pb=new QPushButton();   pb->setText("AAA");	pb->move(22,22); 
    pb->setParent(&w);//设置父对象
     //注册过滤器对象
    pb->installEventFilter(&ma);     	pb->installEventFilter(&mb); 
    pb->installEventFilter(&mc);		pb->installEventFilter(&mc1);
    w.resize(333,222);    w.show();    a.exec();       return 0;     }
  • 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

程序运行结果及说明(见图2-15)
在这里插入图片描述
按钮AAA安装的过滤器对象依次为ma,mb,mc,mc1,
因此按下鼠标时,依次调用对象mc1,mc,mb,ma(即逆序)
的eventFilter函数,需要注意的是:当安装了多个事件过滤
器之后,eventFilter函数返回0并不会使事件返回给目标对
象,而是传递给下一个过滤器对象,当所有过滤器对象都不处理该事件时才会传递给目标对象。
2.6.6 自定义事件与事件的发送(若有需要请留言,然后视情况发表)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt事件过滤器原理EventFilter(installEventFilter函数) 的相关文章

随机推荐

  • Android学习——Adapter适配器

    AdapterView 容器控件 其整体效果由每一个子元素内容决定 子元素的形式由Adapter决定 AdapterView的子视图对象 ListView 以垂直滑动列表形式显示一组数据 GridView 以网格形式显示一组数据 Spinn
  • GPUView的使用

    本文翻译自GPUView的开发者Matt的blog https graphics stanford edu mdfisher GPUView html GPUview可以在 https docs microsoft com en us wi
  • 10个经典的C语言面试基础算法及代码

    本文是码农网原创整理 转载请看清文末的转载要求 谢谢合作 算法是一个程序和软件的灵魂 作为一名优秀的程序员 只有对一些基础的算法有着全面的掌握 才会在设计程序和编写代码的过程中显得得心应手 本文是近百个C语言算法系列的第二篇 包括了经典的F
  • C语言(Head First C)-5_1:使用多个源文件:数据类型和使用头文件声明函数

    该系列文章系个人读书笔记及总结性内容 任何组织和个人不得转载进行商业活动 5 1 使用多个源文件 数据类型和头文件 大程序不等于大源文件 只有一个源文件的话 维护耗时且困难 如何把源文件分解为易于管理的小模块 然后合成一个大程序 正是本章的
  • Append-only及其使用

    Append only 维基百科 Append only 是计算机数据存储的一种属性 将新数据附加到存储中 但现有数据是不可变的 许多数据结构和数据库实现了不可变对象 有效地使它们的数据结构只能追加 实现仅追加数据结构有很多好处 例如确保数
  • android 播放raw音频文件格式,Android 使用mediaplayer播放res/raw文件夹中的音乐的实例...

    Android 使用mediaplayer播放res raw文件夹中的音乐的实例 1 在res文件夹中新建一个文件夹重命名为raw 并且将要播放的音乐放到raw文件夹里面 2 修改layout目录下的xml布局文件 添加3个按钮空间和一个文
  • 计算机硬盘启动设置方法,bios设置硬盘启动,详细教您bios设置硬盘启动操作步骤...

    我们在操作电脑的时候 会遇到要重装系统的情况 每当这种时候我们就会想到通过bios设置来进行系统的重装 所以今天小编就来重点给你们说说关于bios设置硬盘启动的操作步骤 重装系统是我们在使用电脑的时候会经常在遇到问题时采用的解决方法 但说到
  • spring boot 获取yaml配置的对象和数组对象

    一 获取对象 例子 yaml中的配置 permission method POST path auth login spring boot 中 在需要使用到该配置的controller或者service或者专门的配置类中 添加method和
  • 磁盘加新盘扩容

    注 如果有磁盘超过2T 如下调整 使用parted来对GPT磁盘操作 进入交互式模式 没有的话yum安装下 parted dev sdb 将MBR磁盘格式化为GPT parted mklabel gpt 到这就可以进行下面的了 先查看下新磁
  • QT UI不能索引控件

    原因 Qt程序使用的UI h文件并不是最新的UI文件 最新的ui h在bulid文件夹里面了 软件依旧使用旧的ui h文件 简单讲就是先要从 ui生成ui h然后再编译 所以界面未更新实际上是因为ui h这个文件没有更新导致的 解决办法 1
  • 论文阅读-(GLIP)Grounded Language-Image Pre-training (目标检测+定位)

    Paper Grounded Language Image Pre training Code https github com microsoft GLIP 简介 定位任务与图像检测任务非常类似 都是去图中找目标物体的位置 目标检测为给出
  • 好一场逗鹅冤:一瓶老干妈撬动BAT

    近日 号称 南山必胜客 的腾讯法务部将低调做酱料的老干妈送上了热搜 腾讯状告老干妈欠广告费 老干妈则称腾讯遭遇诈骗 双方各执一词 引得不明真相的吃瓜群众热闹围观 01 腾讯被骗 老干妈躺赚 6月29日 广东省深圳市南山区人民法院发布一则民事
  • QTcpSocket 发送数据心得

    遇到不会用的函数前 最好还是看看手册QAQ 今天居然吃了这个大亏 先交代一下背景 在做TCP客户端的发送数据功能 要和服务器程序进行TCP IP通信 且根据通信协议要发送数组或者结构体 并且数组的每一个位都是有效数据位 因此不能像大多数人一
  • 跳转小程序:wx-open-launch-weapp 注意事项,不显示按钮问题

    JSSDK参考文件 一 注意查看引入JS的版本 版本 版本 引用1 6 引用1 6 引用1 6 http res wx qq com open js jweixin 1 6 0 js 如果不引用1 6会出现什么情况 开放标签列表不显示 所以
  • 浅谈路由器工作原理

    路由器的作用是实现网络的三层通信 将二层网络互联形成一个三层网络 路由器工作内容 1 封装和解封装 网卡CU 数据帧 2 维护路由表 3 IP转发 也叫网络转发 三层转发 路由器接口特点 路由器接口和计算机网卡接口一样 都能封装和解封装数据
  • 【Python:Pycharm】mmSegmentation语义分割框架教程

    文章目录 一 MMSegmentation介绍 二 MMSegmentation基本框架 1 model设置 2 dataset设置 2 1 Dataset Class文件配置 2 2 Dataset Config文件配置 2 3 Tota
  • C语言实现贪吃蛇(详细版)

    一 需要掌握的知识 C语言基础语法 结构体 指针 链表
  • MyBatis 源码解析MyBatis如何解析配置 ?(六)

    XMLMapperBuilder parameterMapElement 代码比较长了 因为parameterMap 涉及到比较多的东西
  • 基于bandersnatch搭建pip本地源

    由于现在工作在单位局域网环境下 不能联接互联网 Python程序的开发和部署需要很多地三方的包 为了便于在局域网环境下学习和使用Python进行程序开发 特在有互联网的电脑上同步了一份Pip源 定期同步部署到局域网服务器上 查了不少资料 发
  • Qt事件过滤器原理EventFilter(installEventFilter函数)

    Qt事件过滤器原理 installEventFilter函数 本文为原创文章 转载请注明出处 或注明转载自 黄邦勇帅 原名 黄勇 本文出自本人原创著作 Qt5 10 GUI完全参考手册 网盘地址 https pan baidu com s