Qt 基础组件速学 事件过滤器

学习目标:理解事件过滤器

前置环境

运行环境:qt creator 4.12

学习内容和效果演示:

Qt 提供了事件过滤器的机制,允许我们在事件到达目标对象之前对事件进行拦截和处理。这在以下情况下非常有用:

  1. 全局事件处理: 我们可以在应用程序级别安装一个事件过滤器,拦截所有控件的事件,实现全局性的事件处理逻辑。

  2. 事件委托: 我们可以让某个对象代理其他对象的事件处理,比如父窗口处理子控件的事件。

  3. 事件转发: 我们可以将事件转发给其他对象处理,比如将鼠标事件转发给子控件处理。

理解总结:在对象和事件增加中间层,实现对象和事件是n:1的形式

使用事件过滤器的步骤如下:

  1. 创建一个事件过滤器对象,实现 bool eventFilter(QObject*, QEvent*) 函数。该函数用于处理被过滤的事件。

  2. 在需要过滤事件的对象上安装事件过滤器,使用 installEventFilter() 函数。

  3. 在事件过滤器的 eventFilter() 函数中处理事件,并返回 true 表示事件已经被处理,否则返回 false 让事件继续传播。

实验

想要实现下列效果,正常思路是给这三个img分别写对应的鼠标事件,功能效果几乎一样。

为了代码简化,我想让这三个img的事件都面向一个事件,则可使用中间层 事件过滤器。

 

 详细主要代码

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    img1.load("C:/Users/jbj/Pictures/test/a.jpg");
    img2.load("C:/Users/jbj/Pictures/test/b.jpg");
    img3.load("C:/Users/jbj/Pictures/test/c.jpg");
    jpg1 =new QLabel;
    jpg2 =new QLabel;
    jpg3 =new QLabel;

    jpg1->setAlignment(Qt::AlignCenter);
    jpg1->setPixmap(QPixmap::fromImage(img1));

    jpg2->setAlignment(Qt::AlignCenter);
    jpg2->setPixmap(QPixmap::fromImage(img2));

    jpg3->setAlignment(Qt::AlignCenter);
    jpg3->setPixmap(QPixmap::fromImage(img3));

    QHBoxLayout* h=new QHBoxLayout;
    h->addWidget(jpg1);
    h->addWidget(jpg2);
    h->addWidget(jpg3);

    QWidget *wgt=new QWidget(this);
    QVBoxLayout* v= new QVBoxLayout(wgt);
    v->addLayout(h);
    status =new QLabel("鼠标按键提示信息!");
    status->setAlignment(Qt::AlignCenter);
    v->addWidget(status);

    setCentralWidget(wgt);//中心控件

    setGeometry(200,200,600,300);

    // 安装事件过滤
    jpg1->installEventFilter(this);
    jpg2->installEventFilter(this);
    jpg3->installEventFilter(this);

}

MainWindow::~MainWindow()
{
}
/*
 * 这个函数是 QObject 类的一个虚函数,需要在自定义的事件过滤器类中进行重写。
 * 它接受两个参数:
QObject* obj: 事件发生的目标对象。QEvent* event: 正在被处理的事件对象。
函数返回值:
如果事件过滤器处理了这个事件,返回 true。
如果事件过滤器没有处理这个事件,返回 false。这样事件就会继续传播给目标对象。
*/
bool MainWindow::eventFilter(QObject* watch,QEvent*e)   {
    if (watch  == jpg1){
        if(e->type() == QEvent::MouseButtonPress){// 鼠标移动区域事件,发生在窗户区域
            QMouseEvent *m =(QMouseEvent*)e;
            if(m->buttons() & Qt::LeftButton) status->setText("鼠标左键被按下:[左边图片]");
            if(m->buttons() & Qt::MidButton) status->setText("鼠标中键被按下:[左边图片]");
            if(m->buttons() & Qt::RightButton) status->setText("鼠标右键被按下:[左边图片]");

            //对当前图片进行放大2倍 创建了一个 QMatrix 对象,用于存储图像变换矩阵。
            QMatrix matrix;
            matrix.scale(2,2);
            QImage img =img1.transformed(matrix);
            jpg1->setPixmap(QPixmap::fromImage(img));
        }
        if(e->type()== QEvent::MouseButtonRelease)//鼠标松开事件
        {
            status->setText("鼠标按键已经释放:[左边图片]");
            jpg1->setPixmap(QPixmap::fromImage(img1));
        }

    }

    if (watch  == jpg2){
        if(e->type() == QEvent::MouseButtonPress){// 鼠标移动区域事件,发生在窗户区域
            QMouseEvent *m =(QMouseEvent*)e;
            if(m->buttons() & Qt::LeftButton) status->setText("鼠标左键被按下:[中间图片]");
            if(m->buttons() & Qt::MidButton) status->setText("鼠标中键被按下:[中间图片]");
            if(m->buttons() & Qt::RightButton) status->setText("鼠标右键被按下:[中间图片]");

            //对当前图片进行放大2倍
            QMatrix matrix;
            matrix.scale(2,2);
            jpg2->setPixmap(QPixmap::fromImage(img2.transformed(matrix)));
        }
        if(e->type()== QEvent::MouseButtonRelease)//鼠标松开事件
        {
            status->setText("鼠标按键已经释放:[中间图片]");
            jpg2->setPixmap(QPixmap::fromImage(img2));
        }

    }

    if (watch  == jpg3){
        if(e->type() == QEvent::MouseButtonPress){// 鼠标移动区域事件,发生在窗户区域
            QMouseEvent *m =(QMouseEvent*)e;
            if(m->buttons() & Qt::LeftButton) status->setText("鼠标左键被按下:[右边图片]");
            if(m->buttons() & Qt::MidButton) status->setText("鼠标中键被按下:[右边图片]");
            if(m->buttons() & Qt::RightButton) status->setText("鼠标右键被按下:[右边图片]");

            //对当前图片进行放大2倍
            QMatrix matrix;
            matrix.scale(2,2);
            jpg3->setPixmap(QPixmap::fromImage(img3.transformed(matrix)));
        }
        if(e->type()== QEvent::MouseButtonRelease)//鼠标松开事件
        {
            status->setText("鼠标按键已经释放:[右边图片]");
            jpg3->setPixmap(QPixmap::fromImage(img3));
        }

    }
    return QMainWindow::eventFilter(watch,e);
}

总结:

Qt 事件过滤器的主要特点和使用场景:

  1. 事件拦截和处理:

    • 事件过滤器允许我们在事件到达目标对象之前对事件进行拦截和处理。
    • 我们可以在 eventFilter() 函数中检查和处理各种类型的事件,如鼠标事件、键盘事件、paint 事件等。
  2. 自定义事件处理逻辑:

    • 通过事件过滤器,我们可以实现各种自定义的事件处理逻辑,如全局性的事件处理、事件委托和事件转发等。
    • 这在需要跨控件或跨对象进行事件处理时非常有用。
  3. 安装和使用:

    • 我们需要创建一个自定义的事件过滤器类,并实现 eventFilter() 函数。
    • 然后在需要过滤事件的对象上安装事件过滤器,使用 installEventFilter() 函数。
  4. 常见使用场景:

    • 全局事件处理: 在应用程序级别安装事件过滤器,拦截所有控件的事件,实现全局性的事件处理逻辑。
    • 事件委托: 让某个对象代理其他对象的事件处理,比如父窗口处理子控件的事件。
    • 事件转发: 将事件转发给其他对象处理,比如将鼠标事件转发给子控件处理。
  5. 返回值含义:

    • 如果事件过滤器处理了这个事件,返回 true
    • 如果事件过滤器没有处理这个事件,返回 false。这样事件就会继续传播给目标对象。

总之,事件过滤器是 Qt 提供的一个强大的机制,可以帮助我们实现各种复杂的事件处理逻辑。它的核心是 eventFilter() 函数,通过对这个函数的实现,我们可以根据需求灵活地拦截和处理事件。

最后附上源代码链接
对您有帮助的话,帮忙点个star

28-event-fillter · jbjnb/Qt demo - 码云 - 开源中国 (gitee.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/776333.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构——(双)链表

文章目录 1. 定义 2. 双链表和单链表的区别 3. 代码示例 3.1 双链表节点和结构定义 3.2 初始化双链表 3.3 返回双链表的长度 3.4 在指定位置插入元素 3.5 在末尾插入元素 3.6 删除指定位置的元素并返回被删除的元素 3.7 删除末尾元素 3.8 获取指定位置的元素 3.9 修…

【IT领域新生必看】探索Java中的对象创建:深入理解`new`与`clone`的对比

文章目录 引言什么是new关键字?使用new关键字的基本语法示例: 什么是clone方法?使用clone方法的基本语法示例: new与clone的区别内存分配与初始化调用方式适用场景性能 new关键字的优缺点优点缺点 clone方法的优缺点优点缺点 深入…

机器学习---线性回归

1、线性回归 例如:对于一个房子的价格,其影响因素有很多,例如房子的面积、房子的卧室数量、房子的卫生间数量等等都会影响房子的价格。这些影响因子不妨用 x i x_{i} xi​表示,那么房价 y y y可以用如下公式表示: y …

【贪心 堆 优先队列】502. IPO

本文涉及知识点 贪心 堆 优先队列 LeetCode502. IPO 假设 力扣(LeetCode)即将开始 IPO 。为了以更高的价格将股票卖给风险投资公司,力扣 希望在 IPO 之前开展一些项目以增加其资本。 由于资源有限,它只能在 IPO 之前完成最多 k…

评价ChatGPT与强人工智能的未来

在人工智能领域,ChatGPT的出现无疑是一个里程碑事件。它不仅展示了自然语言处理技术的巨大进步,也引发了人们对于强人工智能(AGI)的无限遐想。本文将从多个角度评价ChatGPT,并探讨强人工智能距离我们还有多远。 ChatGP…

【Leetcode笔记】406.根据身高重建队列

文章目录 1. 题目要求2.解题思路 注意3.ACM模式代码 1. 题目要求 2.解题思路 首先,按照每个人的身高属性(即people[i][0])来排队,顺序是从大到小降序排列,如果遇到同身高的,按照另一个属性(即p…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【密钥导入介绍及算法规格】

密钥导入介绍及算法规格 如果业务在HUKS外部生成密钥(比如应用间协商生成、服务器端生成),业务可以将密钥导入到HUKS中由HUKS进行管理。密钥一旦导入到HUKS中,在密钥的生命周期内,其明文仅在安全环境中进行访问操作&a…

类继承-多继承虚继承

#include<iostream> using namespace std; class A1 { public:int a 10;}; class A2 { public:int b 20; }; class B :public A1, public A2 { public:int c 30; }; int main(){B b;cout << b.a << b.b << b.c << endl;return 0; } 如果基类…

十五、小型电脑没有数字键及insert,怎么解决IDEA快速插入getset构造这些方法

&#x1f33b;&#x1f33b;目录 一、小型电脑没有数字键及insert&#xff0c;怎么解决IDEA快速插入getset构造这些方法 一、小型电脑没有数字键及insert&#xff0c;怎么解决IDEA快速插入getset构造这些方法 解决&#xff1a; 1.winR打开搜索 2.osk回车 屏幕就出现了这样的一…

windows USB 设备驱动开发- 不同模型下的控制传输

在不同的模型下&#xff0c;USB控制传输会有不同的特点&#xff0c;但是任何控制传输的目标都始终是默认端点。 接收者是设备的实体&#xff0c;其信息&#xff08;描述符、状态等&#xff09;是主机感兴趣的。请求可进一步分为&#xff1a;配置请求、功能请求和状态请求。 发…

二刷力扣——单调栈

739. 每日温度 单调栈应该从栈底到栈顶 是递减的。 找下一个更大的 &#xff0c;用递减单调栈&#xff0c;就可以确定在栈里面的每个比当前元素i小的元素&#xff0c;下一个更大的就是这个i&#xff0c;然后弹出并记录&#xff1b;然后当前元素i入栈&#xff0c;仍然满足递减…

基于.NET开源游戏框架MonoGame实现的开源项目合集

前言 今天分享一些基于.NET开源游戏框架MonoGame实现的开源项目合集。 MonoGame项目介绍 MonoGame是一个简单而强大的.NET框架&#xff0c;使用C#编程语言可以创建桌面PC、视频游戏机和移动设备游戏。它已成功用于创建《怒之铁拳4》、《食肉者》、《超凡蜘蛛侠》、《星露谷物…

linux之管道重定向

管道与重定向 一、重定向 将原输出结果存储到其他位置的过程 标准输入、标准正确输出、标准错误输出 ​ 进程在运行的过程中根据需要会打开多个文件&#xff0c;每打开一个文件会有一个数字标识。这个标识叫文件描述符。 进程使用文件描述符来管理打开的文件&#xff08;FD--…

【Dell R730 折腾记录】风扇调速--在 Ubuntu 系统上开机自启动并每隔30分钟执行一次风扇定速脚本

前段时间升级了一下机柜里的服务器&#xff0c;替换掉了一台旧的 Dell 服务器&#xff0c;换上了这台 R730。但是无奈于噪音的袭扰&#xff0c;搁置了一段时间。我在这台机器上目前安装了一块 Intel Xeon E5-2630v3 芯片以及一张改过散热的 NVIDIA Tesla P4 计算卡。结果就是散…

电脑硬盘分区的基本步骤(2个实用的硬盘分区方法)

在现代计算机中&#xff0c;硬盘分区是非常重要的一步。无论是新硬盘的初始化&#xff0c;还是重新组织现有硬盘&#xff0c;分区都是必不可少的操作。本文将详细介绍电脑硬盘分区的基本步骤&#xff0c;帮助您更好地管理和利用硬盘空间。 文章开始&#xff0c;我们先简单说一…

【C++】类和对象3.0

浅浅介绍最近所学&#xff0c;希望有兴趣的读者老爷垂阅&#xff01; 目录 1.再谈构造函数 1.1.构造函数体赋值 1.2.初始化列表 1.3.构造函数的小知识 2. explicit关键字 3.static成员 3.1.static成员概念 3.2.static成员特性 4.友元 4.1.友元函数 4.2.友元类 5…

七、Linux二进制安装Redis集群

目录 七、Linux二进制安装Redis集群1 安装Redis所需依赖2 单机安装Redis&#xff08;7.2.4&#xff09;2.1 下载Redis2.2 安装Redis 3 分布式部署模式&#xff08;Redis Cluster&#xff09;3.1 分布式部署模式的配置文件3.2创建集群 4 主从复制模式&#xff08;Redis Sentinel…

jenkins搭建部署前端工程 ,从0到1

一.java环境配置 1 安装tomcatjdk17 这个也行 3 安装maven3.3.9 安装教程参考 4 安装Jenkins 下载地址 参考教程 二、相关配置 1 访问http://localhost:8080/jenkins&#xff0c;进入Jenkins初始化页面&#xff0c;第一次启动时间可能有点长&#xff0c;耐心等待。进入成功后会…

AndroidKille不能用?更新apktool插件-cnblog

AndroidKiller不更新插件容易报错 找到apktool管理器 填入apktool位置&#xff0c;并输入apktool名字 选择默认的apktool版本 x掉&#xff0c;退出重启 可以看到反编译完成了

《Windows API每日一练》8.3 scrollbar控件

在第三章SYSMETS2.C实例中&#xff0c;我们是通过CreateWindow函数创建窗口的参数窗口样式中添加垂直或水平滚动条。本节我们将讲述作为子窗口控件的滚动条。 本节必须掌握的知识点&#xff1a; 滚动条类 滚动条控件和着色 8.3.1 滚动条类 ■窗口滚动条与滚动条控件的异同 …