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

news/2024/7/18 10:14:38 标签: 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.niftyadmin.cn/n/5544154.html

相关文章

探索数据的奥秘:sklearn中的聚类分析技术

探索数据的奥秘:sklearn中的聚类分析技术 在数据科学领域,聚类分析是一种无监督学习方法,它的目标是将数据集中的样本划分为多个组或“簇”,使得同一组内的样本相似度高,而不同组间的样本相似度低。scikit-learn&…

Eclipse运行main函数报 launch error

右键run as java application,运行main函数的时候报launch error 解决方式:文件右键run configurations 旧的是Project JRE,改成下图这个样子

得帆受邀参加中国信通院 2024低代码·无代码产业大会,共同探索低代码与大模型的新未来

2024年6月26日,由中国通信标准化协会主办,中国通信标准化协会云计算标准和开源推进委员会承办的2024低代码无代码产业大会在北京召开,大会以“智融低无码,模创新未来”为主题,发布领域研究成果,交流行业前沿…

目标检测YOLO实战应用案例100讲-基于深度学习的无人机影像小目标识别(续)

目录 3.2 实验平台和环境 3.3 实验评价指标 3.4 基础框架YOLOv5在无人机数据集上的实验 3.4.1 实验结果 3.4.2 结果分析 4基于深度学习的无人机影像目标检测算法 4.1 基于改进YOLOv5的小目标检测算法研究 4.1.1 增加注意力机制 4.1.2 增加检测层 4.1.3多尺…

关于隐藏、覆盖(重写)、重载的理解

定义区分 在派生-对象中:优先考虑隐藏,此时派生类中的覆盖(重写)也是隐藏;没有隐藏的情况下,子类对象才能调用父类重载函数。[此时感觉virtual没用,]在派生-指针或者引用中:只用覆盖(重写)和重载; 注:C Pr…

创建一个AXIS的初始IP核

参考自:https://www.cnblogs.com/milianke/p/17936380.html 以该博主文章为主,本文章做补充。 注意的点: edit ip 在导出axis的主机和从机的时候,记得选择edit ip,这样才能看到从机和主机的源代码,然后…

如何使用matplotlib绘制可以指定大小的饼图

​ 如果想绘制指定大小的饼图,如直径5mm,可以参考本博文实现。 有此需求的起因是我有两个维度的数据想要用图形展示,第一个维度是每种场景下2021,2022和2023年的总容量,第二个维度是每种场景下2021,2022和…

经济寒冬:竞品凶猛,你的产品如何求生?

那些年曾被竞品干掉的产品 1997年到2010年左右是国内互联网行业的快速发展和多元化发展的时期,这一时期涌现出来一大批优秀的产品,市场竞争越来越激烈。苹果 在20 世纪 80 年代,乔布斯的苹果电脑,在当时可是PC行业的老大&#xf…