qt-C++笔记之事件过滤器

qt-C++笔记之事件过滤器

—— 杭州 2024-02-25


在这里插入图片描述

code review!

文章目录

  • qt-C++笔记之事件过滤器
    • 一.使用事件过滤器和不使用事件过滤器对比
      • 1.1.使用事件过滤器
      • 1.2.不使用事件过滤器
      • 1.3.比较
    • 二.Qt 中事件过滤器存在的意义
    • 三.为什么要重写QObject的eventFilter方法?使用QObject默认的eventFilter方法不可以吗?
    • 四.事件过滤器的使用场景
      • 4.1. 灵活的事件处理:
      • 4.2. 代码解耦:
      • 4.3. 条件事件处理:
      • 4.4. 监控和调试:
      • 4.5. 创建可重用的行为:
    • 五.使用事件过滤器和不使用事件过滤器优缺点
      • 使用事件过滤器
      • 不使用事件过滤器
    • 六.《Qt6 C++开发指南》——事件过滤器部分
    • 七.《Qt程序设计基础 基于银河麒麟桌面操作系统》

一.使用事件过滤器和不使用事件过滤器对比

在Qt框架中,事件过滤器通常通过重写QObject类的eventFilter()方法来实现。下面提供两个简单的示例,展示在Qt C++中使用和不使用事件过滤器的情况:

1.1.使用事件过滤器

首先,创建一个新的类(例如MyFilter),从QObject派生,并重写eventFilter()方法来拦截和处理特定的事件。

#include <QObject>
#include <QEvent>
#include <QDebug>class MyFilter : public QObject {Q_OBJECTprotected:bool eventFilter(QObject *obj, QEvent *event) override {if (event->type() == QEvent::KeyPress) {qDebug() << "A key press event has been filtered.";// 处理事件return true;  // 返回true表示事件已被处理,不需要进一步传递}// 其他事件传递给基类的eventFilter方法return QObject::eventFilter(obj, event);}
};

然后,你需要在你想要过滤其事件的对象上安装这个过滤器:

#include <QApplication>
#include <QWidget>int main(int argc, char *argv[]) {QApplication a(argc, argv);QWidget window;MyFilter *filter = new MyFilter(&window);window.installEventFilter(filter);  // 安装事件过滤器window.show();return a.exec();
}

1.2.不使用事件过滤器

如果不使用事件过滤器,你可能会直接在对象的事件处理方法中处理所有的事件,例如在QWidget的子类中重写keyPressEvent()方法:

#include <QWidget>
#include <QKeyEvent>
#include <QDebug>class MyWidget : public QWidget {Q_OBJECTprotected:void keyPressEvent(QKeyEvent *event) override {qDebug() << "A key press event has been received.";// 处理事件QWidget::keyPressEvent(event);  // 调用基类的keyPressEvent方法}
};int main(int argc, char *argv[]) {QApplication a(argc, argv);MyWidget window;window.show();return a.exec();
}

在这个例子中,MyWidget会接收并处理所有的按键事件,而不是通过一个单独的过滤器来进行筛选。

1.3.比较

使用事件过滤器的方式更加灵活,因为你可以在不修改原有类的情况下,通过安装或移除过滤器来动态改变事件处理行为。此外,过滤器可以用于多个对象,不需要为每个对象编写重复的事件处理代码。

而不使用事件过滤器的方式更加直接,通常用于处理特定对象的事件。这种方式能够保证事件不会被其他对象意外截获,但是如果需要在多个对象之间共享相同的事件处理逻辑,可能会导致代码重复。

二.Qt 中事件过滤器存在的意义

Qt框架中的事件过滤器(Event Filter)是一个强大的功能,它允许对象拦截和处理发给其他对象的事件。事件过滤器的存在意义主要体现在以下几个方面:

  1. 灵活的事件处理:在Qt中,通常情况下,事件是被发送到目标对象的事件处理函数中(如mousePressEventkeyPressEvent等)。通过安装事件过滤器,你可以在事件到达目标对象之前对其进行拦截和处理,这允许你在不修改目标对象代码的情况下增加额外的行为。

  2. 代码解耦:事件过滤器可以帮助你减少类之间的耦合。例如,可以在一个单独的类中处理所有相关的事件,而不是将这些处理逻辑分散到多个子类中。

  3. 条件事件处理:你可以根据需要决定是否要处理某个事件,或者在某些条件满足时改变事件的行为。事件过滤器可以基于动态条件(如应用程序的状态)来决定是否和如何处理事件。

  4. 监控和调试:事件过滤器可以用来监控事件流,帮助开发者理解事件是如何在应用程序中流转的,这对于调试事件相关的问题非常有用。

  5. 创建可重用的行为:通过事件过滤器,可以创建可以附加到多个对象上的通用行为,而无需每个对象都实现相同的事件处理代码。

要使用事件过滤器,你需要重写QObjecteventFilter方法,并使用installEventFilter方法将过滤器对象安装到目标对象上。当事件发生并且传递给目标对象之前,eventFilter方法会被调用,你可以在这个方法中决定如何处理事件。

下面是一个简单的例子,说明如何为一个对象安装事件过滤器:

class MyEventFilter : public QObject
{
protected:bool eventFilter(QObject *obj, QEvent *event) override{if (event->type() == QEvent::KeyPress) {// 处理按键事件// ...return true; // 返回true表示事件被处理,不再传递}// 将事件传递给基类的事件过滤器return QObject::eventFilter(obj, event);}
};// 在某个地方使用事件过滤器
MyEventFilter *filter = new MyEventFilter();
targetObject->installEventFilter(filter);

在这个例子中,MyEventFilter类重写了eventFilter方法来处理按键事件。当目标对象targetObject接收到按键事件时,eventFilter方法会被调用,我们可以在这里决定如何处理该事件。如果我们返回true,则表示事件已经被处理并且不应该继续传递;如果返回false,事件将会继续传递给目标对象的相应事件处理方法。

三.为什么要重写QObject的eventFilter方法?使用QObject默认的eventFilter方法不可以吗?

在Qt中,QObject类提供了一个默认的实现eventFilter方法,但这个默认实现只是简单地返回false,表示它没有处理该事件,事件应该继续传递给目标对象的事件处理方法。换句话说,如果你不重写eventFilter方法,那么安装事件过滤器将没有任何实际效果,因为所有事件都会按照正常的流程继续传递。

重写eventFilter方法的目的是为了在事件到达目标对象之前介入处理流程。你可以在这个方法中编写自定义的逻辑来决定是否拦截某个事件,改变事件的默认行为,或者在事件传递到目标对象之前进行一些特殊处理。

下面是QObjecteventFilter方法默认实现的伪代码表示:

bool QObject::eventFilter(QObject *watched, QEvent *event)
{// 默认实现,不做任何处理,返回false表示不拦截事件return false;
}

当你创建一个新的类继承自QObject或者其子类,并且你希望该类能够以某种方式处理或者监控其他对象的事件时,你就需要提供eventFilter的自定义实现。例如,你可能想要记录所有的鼠标点击事件,或者在用户按下特定快捷键时触发某个动作。这时,你就需要重写eventFilter方法,如下所示:

class MyCustomFilter : public QObject
{// ...protected:bool eventFilter(QObject *watched, QEvent *event) override{if (event->type() == QEvent::MouseButtonPress) {// 处理鼠标按下事件// ...return true; // 事件被处理,不再传递}// 对于不处理的事件,调用基类的eventFilter方法return QObject::eventFilter(watched, event);}
};

在这个例子中,MyCustomFilter类重写了eventFilter方法以便在鼠标按下时执行一些自定义操作。如果eventFilter方法返回true,则表示事件已经被处理,不应该继续传递;如果返回false,则事件会按照正常的事件处理流程继续传递给目标对象。

四.事件过滤器的使用场景

当然可以,下面是针对每个场景的main.cpp文件的完整示例。

4.1. 灵活的事件处理:

#include <QApplication>
#include <QLineEdit>
#include <QDebug>
#include <QObject>class HelpEventFilter : public QObject {
protected:bool eventFilter(QObject *obj, QEvent *event) override {if (event->type() == QEvent::KeyPress) {QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);if (keyEvent->key() == Qt::Key_F1) {qDebug() << "Help requested for:" << obj;return true;}}return QObject::eventFilter(obj, event);}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);QLineEdit lineEdit;HelpEventFilter helpFilter;lineEdit.installEventFilter(&helpFilter);lineEdit.show();return app.exec();
}

4.2. 代码解耦:

#include <QApplication>
#include <QWidget>
#include <QDebug>
#include <QObject>class UpdateEventFilter : public QObject {
protected:bool eventFilter(QObject *obj, QEvent *event) override {if (event->type() == QEvent::MouseButtonPress) {qDebug() << "Updating components due to click on:" << obj;return true;}return QObject::eventFilter(obj, event);}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);QWidget widget;UpdateEventFilter updateFilter;widget.installEventFilter(&updateFilter);widget.show();return app.exec();
}

4.3. 条件事件处理:

#include <QApplication>
#include <QWidget>
#include <QDebug>
#include <QObject>class GameEventFilter : public QObject {bool gameRunning;public:GameEventFilter(bool running) : gameRunning(running) {}protected:bool eventFilter(QObject *obj, QEvent *event) override {if (event->type() == QEvent::KeyPress && gameRunning) {qDebug() << "Game is running - event processed for:" << obj;return true;}return QObject::eventFilter(obj, event);}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);QWidget widget;GameEventFilter gameFilter(true);widget.installEventFilter(&gameFilter);widget.show();return app.exec();
}

4.4. 监控和调试:

#include <QApplication>
#include <QWidget>
#include <QDebug>
#include <QObject>class DebugEventFilter : public QObject {
protected:bool eventFilter(QObject *obj, QEvent *event) override {qDebug() << "Event:" << event->type() << "for object:" << obj;return QObject::eventFilter(obj, event);}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);QWidget widget;DebugEventFilter debugFilter;widget.installEventFilter(&debugFilter);widget.show();return app.exec();
}

4.5. 创建可重用的行为:

#include <QApplication>
#include <QWidget>
#include <QDebug>
#include <QObject>
#include <QDragEnterEvent>
#include <QMimeData>class DragDropEventFilter : public QObject {
protected:bool eventFilter(QObject *obj, QEvent *event) override {if (event->type() == QEvent::DragEnter) {QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent *>(event);if (dragEvent->mimeData()->hasFormat("text/plain")) {qDebug() << "Drag enter event for:" << obj;dragEvent->accept();return true;}}return QObject::eventFilter(obj, event);}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);QWidget widget;widget.setAcceptDrops(true);DragDropEventFilter dragDropFilter;widget.installEventFilter(&dragDropFilter);widget.show();return app.exec();
}

在每个例子中,我们创建了一个应用程序实例和一个主窗口部件,然后创建了一个事件过滤器并将其安装到主窗口部件上。在实际应用中,你可能需要调整过滤器逻辑以适应你的具体需求。这些示例中的eventFilter函数的返回值很重要,如果它返回true,则表明事件已被处理,不会再传递给对象;如果返回false,则事件会继续传递给对象的event方法。

五.使用事件过滤器和不使用事件过滤器优缺点

在计算机编程和系统设计中,事件过滤器是一种用来决定是否应该处理或忽略某个事件的机制。事件可以是用户操作、系统生成的消息或者是由硬件设备产生的信号等。使用事件过滤器和不使用事件过滤器可以带来不同的效果和影响,下面列举了一些对比点:

使用事件过滤器

优点:

  1. 效率提升:当事件数量很大时,过滤器可以帮助减少无关事件的处理,从而节省CPU时间和内存资源。
  2. 更好的用户体验:过滤器可以确保只有相关和重要的事件被处理,避免了不必要的干扰,提高应用程序的响应性。
  3. 可维护性:过滤器可以帮助组织和管理事件处理逻辑,使代码更加清晰,易于维护和更新。
  4. 灵活性:过滤器可以动态地添加或移除,方便地调整哪些事件应该被处理。
  5. 安全性:过滤掉不必要的或潜在危险的事件,可以减少安全风险。

缺点:

  1. 复杂性:设计和实现事件过滤器会增加系统的复杂度。
  2. 性能开销:虽然过滤器可以提高整体效率,但是过滤器本身的运行也会消耗一定的性能。
  3. 可能的错误过滤:如果过滤器逻辑设计不当,可能会错误地过滤掉应该处理的事件。

不使用事件过滤器

优点:

  1. 简单性:不需要考虑过滤逻辑,实现起来比较简单直接。
  2. 无额外性能开销:没有过滤器运行的开销,每个事件都直接送进事件处理流程。
  3. 完整性:所有事件都会被送至处理程序,没有遗漏的风险。

缺点:

  1. 效率低下:没有过滤机制意味着所有事件,无论是否相关,都会被处理,这可能会导致不必要的性能负担。
  2. 用户体验不佳:处理大量无关事件可能会导致应用程序响应变慢,影响用户体验。
  3. 可维护性差:随着事件处理逻辑的增多,代码可能变得难以管理和维护。
  4. 安全风险:处理所有事件可能会使系统面临更多的安全威胁,因为不加选择的处理可能包含恶意的事件。

总结来说,使用事件过滤器可以帮助提高系统效率,提升用户体验,加强安全性,并有助于代码维护。然而,它也会带来额外的复杂性和性能开销。不使用事件过滤器则在实现上更为简单,但可能会导致效率低下和维护困难等问题。在实际应用中,是否使用事件过滤器取决于具体的需求、资源限制和安全考虑。

六.《Qt6 C++开发指南》——事件过滤器部分

在这里插入图片描述

七.《Qt程序设计基础 基于银河麒麟桌面操作系统》

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【服务器数据恢复】通过reed-solomon算法恢复raid6数据的案例

服务器数据恢复环境&#xff1a; 一台网站服务器中有一组由6块磁盘组建的RAID6磁盘阵列&#xff0c;操作系统层面运行MySQL数据库和存放一些其他类型文件。 服务器故障&#xff1a; 该服务器在工作过程中&#xff0c;raid6磁盘阵列中有两块磁盘先后离线&#xff0c;不知道是管理…

力扣--动态规划1027.最长等差数列

思路分析&#xff1a; 使用动态规划的思想&#xff0c;定义二维数组dp&#xff0c;其中dp[i][j]表示以nums[i]为结尾&#xff0c;公差为(j-1000)的等差数列长度。为了适应负数的情况&#xff0c;将公差的范围设为[-1000, 1000]&#xff0c;并且加上1000作为数组索引。 初始化r…

2024年环境安全科学、材料工程与制造国际学术会议(ESSMEM2024)

【EI检索】2024年环境安全科学、材料工程与制造国际学术会议&#xff08;ESSMEM2024) 会议简介 我们很高兴邀请您参加将在三亚举行的2024年环境安全科学、材料工程和制造国际学术会议&#xff08;ESSMEM 2024&#xff09;。 ESSMEM2024将汇集世界各国和地区的研究人员&…

HarmonyOS创建一个ArkTS卡片

创建一个ArkTS卡片 在已有的应用工程中&#xff0c;创建ArkTS卡片&#xff0c;具体操作方式如下。 创建卡片。 根据实际业务场景&#xff0c;选择一个卡片模板。 在选择卡片的开发语言类型&#xff08;Language&#xff09;时&#xff0c;选择ArkTS选项&#xff0c;然后单…

vscode使用restClient实现各种http请求

vscode使用restClient实现各种http请求 一&#xff0c;安装插件 首先&#xff0c;我们要在vscode的扩展中&#xff0c;搜索rest Client&#xff0c;然后安装它&#xff0c;这里我已经安装过了。 安装后&#xff0c;我们就可以使用rest client插件进行http各种操作了。 二&…

项目解决方案:街道社区视频监控接入、汇聚和联网设计方案

目 录 一、客户需求 二、网络拓扑图 三、方案描述 四、系统配置 1、服务器配置 2、带宽配置 五、方案优势 1. 平台可堆叠使用 2. 支持主流接入协议 4. 多种终端显示 5. 客户端功能强大 6. 一机一档 一、客户需求 1&#xff0c;一个街道有十个社…

Orange3数据预处理(列选择组件)数据角色及类型描述

在Orange3的文件组件中&#xff0c;datetime、categorical、numeric以及text代表不同种类的数据类型&#xff0c;具体如下&#xff1a; datetime&#xff1a;代表日期和时间类型的数据。通常用于时间序列分析、生存分析和其他需要考虑时间因素的机器学习任务中。例如&#xff0…

纽约纳斯达克大屏投放受众群体有哪些-大舍传媒

纽约纳斯达克大屏投放受众群体有哪些-大舍传媒 1. 纳斯达克大屏的概述 纳斯达克大屏是全球金融市场中最出名的电子交易平台之一。作为一个重要的金融信息传递渠道&#xff0c;纳斯达克大屏吸引了来自全球的投资者的目光。在这个巨大的投放平台上&#xff0c;大舍传媒希望为客…

【Flink精讲】Flink性能调优:内存调优

内存调优 内存模型 JVM 特定内存 JVM 本身使用的内存&#xff0c;包含 JVM 的 metaspace 和 over-head 1&#xff09; JVM metaspace&#xff1a; JVM 元空间 taskmanager.memory.jvm-metaspace.size&#xff0c;默认 256mb 2&#xff09; JVM over-head 执行开销&#xff1…

【小沐学QT】QT学习之Web控件的使用

文章目录 1、简介1.1 Qt简介1.2 Qt下载和安装1.3 Qt快捷键1.4 Qt帮助 2、QtWeb控件2.1 测试代码1&#xff08;QApplication&#xff09;2.2 测试代码2&#xff08;QApplicationQWidget&#xff09;2.3 测试代码3&#xff08;QApplicationQMainWindow&#xff09;2.4 测试代码4&…

关系型数据库事务的四性ACID:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)

关系型数据库事务的四性ACID:原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Isolation&#xff09;和持久性&#xff08;Durability&#xff09; 事务的四性通常指的是数据库事务的ACID属性&#xff0c;包括原子性&…

【计算机网络】传输层——TCP和UDP详解

文章目录 一. TCP和UDP简介二. UDP 协议详解1. UDP报文格式2. UDP的使用场景 三. TCP 协议详解1. TCP报文格式2. TCP协议的重要机制确认应答&#xff08;保证可靠传输的最核心机制&#xff09;超时重传连接管理&#xff08;三次握手、四次挥手&#xff09;&#xff01;&#xf…

Java+SpringBoot+Vue+MySQL:疫情隔离酒店管理的全面技术解决方案

✍✍计算机毕业编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java、…

vue video 多个视频切换后视频不显示的解决方法

先说一下我这边的需求是视频需要轮播&#xff0c;一个人员有多个视频&#xff0c;左右轮播是轮播某个人员下的视频&#xff0c;上下切换是切换人员。 vue 代码 <el-carouselindicator-position"none"ref"carousel"arrow"always":interval&qu…

国产替代MATLAB的征途

国产替代MATLAB的征途 The Journey of Domestic Alternatives to MATLAB 在科技的浪潮中&#xff0c;软件成为了推动进步的重要工具。MATLAB&#xff0c;这一工程和科学计算的巨擘&#xff0c;因其强大的数值分析、矩阵运算能力和丰富的应用工具箱&#xff0c;在全球学术界和工…

解决vulhub漏洞环境下载慢卡死问题即解决docker-valhub漏洞环境下载慢的问题

解决vulhub环境下载慢/卡 当前环境为&#xff1a;ubuntu20 1.在 cd /etc/docker/目录下创建或修改daemon.json文件 sudo touch daemon.json编辑daemon.json文件 sudo vim daemon.json2.填写阿里云镜像地址&#xff1a; { "registry-mirrors":["https://6kx…

win10安装使用AxurePR9

背景&#xff1a;win10 安装、汉化 Axure Pr9 下载 安装包 链接&#xff1a;https://pan.baidu.com/s/1taMgh2zLbaFK7VTfUXTHdQ 提取码&#xff1a;kygo 安装 修改安装目录 打开是英文的 汉化 复制lang包到Axure安装包 再打开就是中文 问题 发布html后火狐无法打开 一、…

element table数据量太大,造成浏览器崩溃。解决方案

这是渲染出来的数据 其实解决思路大致就是&#xff1a;把后台返回的上万条数据&#xff0c;进行分割&#xff08;前端分页&#xff09;&#xff0c;这样先加载几十条&#xff0c;然后再用懒加载的方式去concat&#xff0c;完美解决 上代码 <template><div class&quo…

详细分析Pandas中的Series对象(附Demo)

目录 1. 问题所示2. 基本知识3. API Demo4. 示例Demo5. 彩蛋 1. 问题所示 从实战上手基础知识 一开始遇到这个Bug&#xff1a; TypeError: unsupported operand type(s) for -: str and float后面经了解执行减法运算时发生了错误&#xff0c;其中一个操作数是字符串类型&…

Java中PDF文件传输有哪些方法?

专栏集锦&#xff0c;大佬们可以收藏以备不时之需&#xff1a; Spring Cloud 专栏&#xff1a;http://t.csdnimg.cn/WDmJ9 Python 专栏&#xff1a;http://t.csdnimg.cn/hMwPR Redis 专栏&#xff1a;http://t.csdnimg.cn/Qq0Xc TensorFlow 专栏&#xff1a;http://t.csdni…