Qt事件过滤器

2023-10-29

有时候,对象需要查看、甚至要拦截发送到另外对象的事件。例如,对话框可能想要拦截按键事件,不让别的组件接收到;或者要修改回车键的默认处理。

通过前面的章节,我们已经知道,Qt 创建了 QEvent 事件对象之后,会调用 QObject 的 event() 函数处理事件的分发。显然,我们可以在 event() 函数中实现拦截的操作。由于 event() 函数是 protected 的,因此,需要继承已有类。如果组件很多,就需要重写很多个 event() 函数。这当然相当麻烦,更不用说重写 event() 函数还得小心一堆问题。好在 Qt 提供了另外一种机制来达到这一目的:事件过滤器。

QObject 有一个 eventFilter() 函数,用于建立事件过滤器。这个函数的签名如下:

virtual bool QObject::eventFilter ( QObject * watched, QEvent * event );

这个函数正如其名字显示的那样,是一个 “事件过滤器”。所谓事件过滤器,可以理解成一种过滤代码。想想做化学实验时用到的过滤器,可以将杂质留到滤纸上,让过滤后的液体溜走。事件过滤器也是如此:它会检查接收到的事件。如果这个事件是我们感兴趣的类型,就进行我们自己的处理;如果不是,就继续转发。这个函数返回一个 bool 类型,如果你想将参数 event 过滤出来,比如,不想让它继续转发,就返回 true,否则返回 false。事件过滤器的调用时间是目标对象(也就是参数里面的 watched 对象)接收到事件对象之前。也就是说,如果你在事件过滤器中停止了某个事件,那么,watched 对象以及以后所有的事件过滤器根本不会知道这么一个事件。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

我们来看一段简单的代码:

class MainWindow : public QMainWindow
 {
 public:
     MainWindow();
 protected:
     bool eventFilter(QObject *obj, QEvent *event);
 private:
     QTextEdit *textEdit;
 };

 MainWindow::MainWindow()
 {
     textEdit = new QTextEdit;
     setCentralWidget(textEdit);

     textEdit->installEventFilter(this);
 }

 bool MainWindow::eventFilter(QObject *obj, QEvent *event)
 {
     if (obj == textEdit) {
         if (event->type() == QEvent::KeyPress) {
             QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
             qDebug() << "Ate key press" << keyEvent->key();
             return true;
         } else {
             return false;
         }
     } else {
         // pass the event on to the parent class
         return QMainWindow::eventFilter(obj, event);
     }
 }

MainWindow 是我们定义的一个类。我们重写了它的 eventFilter() 函数。为了过滤特定组件上的事件,首先需要判断这个对象是不是我们感兴趣的组件,然后判断这个事件的类型。在上面的代码中,我们不想让 textEdit 组件处理键盘按下的事件。所以,首先我们找到这个组件,如果这个事件是键盘事件,则直接返回 true,也就是过滤掉了这个事件,其他事件还是要继续处理,所以返回 false。对于其它的组件,我们并不保证是不是还有过滤器,于是最保险的办法是调用父类的函数。

eventFilter() 函数相当于创建了过滤器,然后我们需要安装这个过滤器。安装过滤器需要调用 QObject::installEventFilter() 函数。这个函数的签名如下:

void QObject::installEventFilter ( QObject * filterObj )

这个函数接受一个 QObject * 类型的参数。记得刚刚我们说的,eventFilter() 函数是 QObject 的一个成员函数,因此,任意 QObject 都可以作为事件过滤器(问题在于,如果你没有重写 eventFilter() 函数,这个事件过滤器是没有任何作用的,因为默认什么都不会过滤)。已经存在的过滤器则可以通过 QObject::removeEventFilter() 函数移除。

我们可以向一个对象上面安装多个事件处理器,只要调用多次 installEventFilter() 函数。如果一个对象存在多个事件过滤器,那么,最后一个安装的会第一个执行,也就是后进先执行的顺序。

还记得我们前面的那个例子吗?我们使用 event() 函数处理了 Tab 键:

bool CustomWidget::event(QEvent *e)
{
    if (e->type() == QEvent::KeyPress) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(e);
        if (keyEvent->key() == Qt::Key_Tab) {
            qDebug() << "You press tab.";
            return true;
        }
    }
    return QWidget::event(e);
}

现在,我们可以给出一个使用事件过滤器的版本:

bool FilterObject::eventFilter(QObject *object, QEvent *event)
{
    if (object == target && event->type() == QEvent::KeyPress) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        if (keyEvent->key() == Qt::Key_Tab) {
            qDebug() << "You press tab.";
            return true;
        } else {
            return false;
        }
    }
    return false;
}

事件过滤器的强大之处在于,我们可以为整个应用程序添加一个事件过滤器。记得,installEventFilter() 函数是 QObject 的函数,QApplication 或者 QCoreApplication 对象都是 QObject 的子类,因此,我们可以向 QApplication 或者 QCoreApplication 添加事件过滤器。这种全局的事件过滤器将会在所有其它特性对象的事件过滤器之前调用。尽管很强大,但这种行为会严重降低整个应用程序的事件分发效率。因此,除非是不得不使用的情况,否则的话我们不应该这么做。

注意,如果你在事件过滤器中 delete 了某个接收组件,务必将函数返回值设为 true。否则,Qt 还是会将事件分发给这个接收组件,从而导致程序崩溃。

事件过滤器和被安装过滤器的组件必须在同一线程,否则,过滤器将不起作用。另外,如果在安装过滤器之后,这两个组件到了不同的线程,那么,只有等到二者重新回到同一线程的时候过滤器才会有效。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

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

Qt事件过滤器 的相关文章

  • QMutex 是否需要是静态的,以便此类实例的其他线程调用知道暂停其操作?

    从多个线程调用以下附加函数 我不希望数据重写附加 因为计数器尚未增加 除了当前使用 Append 的线程之外 这是否会挂起所有进入的线程 或者其他线程会继续运行而不追加数据吗 互斥锁是否需要是 静态 的 或者每个实例都知道要暂停操作吗 如果
  • 如何在 OS X 上的 Qt 应用程序中设置应用程序图标,足以进行分发?

    跟进这个答案 https stackoverflow com a 20918932 368896 to 这个问题 https stackoverflow com questions 20909341 what is the fastest
  • QStyledItemDelegate 绘制自定义小部件失败

    在我的一个项目中 我使用的是QTableWidget为了显示一些复杂的计算结果 为了提高表格的可读性 我需要在单个表格单元格内显示两个对齐的值 后来我想通过使用颜色或箭头等来进一步自定义小部件 为此我源自QStyledItemDelegat
  • QT:删除QGridLayout中QLabel之间的空格

    我将一些具有不同颜色的 QLabels 添加到 QGridLayout 作为 QWidget 的布局 现在我在每个 Qlabel 与下一个 Qlabel 之间有一个间距 我想将其删除 我尝试将标签的边距设置为 0 将 GridLayout
  • 如何在Qt 5中的paintEvent上使用mouseMoveEvent?

    我是 Qt 和 c 的新手 所以我遇到了一些困难 我正在尝试创建一个小部件 它可以获取 mouseMoveEvent 位置并在鼠标位置的像素图上绘制椭圆 下面你可以看到代码 include myimage h include
  • 如何声明一个带有成员函数指针的函数

    我有一个类 其中的成员变量指向库对象 class myClassA private libraryClass libraryObject 该库类发出事件 以字符串为特征 并提供一种机制 允许客户端类指定在发出事件时应调用的成员函数 因此在m
  • QML 中可重用的字体属性[重复]

    这个问题在这里已经有答案了 在 QML 中 我希望能够定义一组字体属性以进行简单的语义重用 例如 代替 Text text This is a header font family Encode Sans weight Font Black
  • Qt:不完整类型和前向声明的使用无效

    我有一些误解 A h ifndef A H define A H include B h class A public B Q OBJECT public A endif A cpp include A h A A B ui gt blan
  • PyQt4 QPalette 不工作

    btn QtGui QPushButton Button self palettes btn palette palettes setColor btn backgroundRole QtCore Qt green btn setPalet
  • Qt 5.1.1 与 Visual Studio 2012 - 这些 QT 版本无法访问

    打开 Visual Studio 时出现此错误 我安装自http qt project org downloads http qt project org downloads 适用于 Windows 64 位的 Qt 5 1 1 VS 20
  • 无法运行 Qt 应用程序:找不到版本“Qt_5”

    我运行 Ubuntu 16 04 LTS 我的问题是我无法运行可以编译的 Qt5 应用程序 这是我尝试运行它时得到的结果 home user Desktop sconfig dist Release GNU Linux SCongif us
  • QFileSystemModel setRootPath

    我正在尝试创建一个 Qt 应用程序来显示文件夹 Mac OS 中的 Users 文件夹 的内容 这是代码 QFileSystemModel dirModel new QFileSystemModel dirModel gt setRootP
  • 通过单击内部小部件而不是标题栏来移动窗口

    在 Windows 中 当我创建 QMainWindow 时 我可以通过单击标题栏并拖动它来在屏幕上移动它 在我的应用程序中 我使用隐藏了标题栏setWindowFlags Qt CustomizeWindowHint 我正在尝试使用小部件
  • Q风格所有权

    在 Qt 应用程序中使用样式时 我遇到了一个有趣的问题QStyle所有权 QStyle继承自QObject 通常接受QObject parent作为构造函数参数来管理其子级的生命周期 但QStyle的构造函数没有此构造函数参数 第一个问题
  • Qt 相当于 .NET 数据绑定吗?

    Qt 中是否有相当于 NET 数据绑定的功能 我想使用引用数据库中特定实体的 QString 填充一些组合框和其他小部件 但是 如果我可以将数据绑定到这些字符串 而不是基于新的组合框选择再次查询数据库 或者基于构建我自己的将使用 QStri
  • 使用 C++ 访问 Azure blob 存储 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • QByteArray 到整数

    正如您可能从标题中看出的那样 我在转换QByteArray为一个整数 QByteArray buffer server gt read 8192 QByteArray q size buffer mid 0 2 int size q siz
  • 相对文件路径的区别:Qt Creator的调试模式和发布模式

    QFile file test txt if file open QIODevice ReadOnly qDebug lt lt You got me 我在用 Qt 4 8 6 与 MSVC 2010 Qt 创建者 3 1 1 Window
  • Qt 5.3 QPlainTextEdit 更改 QTextCursor 颜色

    我想更改下面的光标颜色QPlainTextEdit小部件 我能够将其宽度设置为6 但我想改变颜色或者它 是否可以 QFontMetrics fm font setCursorWidth fm averageCharWidth setCurs
  • Qt - ubuntu中的串口名称

    我在 Ubuntu 上查找串行端口名称时遇到问题 如您所知 为了在 Windows 上读取串口 我们可以使用以下代码 serial gt setPortName com3 但是当我在 Ubuntu 上编译这段代码时 我无法使用这段代码 se

随机推荐

  • 编译型与解释型、动态语言与静态语言、强类型语言与弱类型语言的区别

    编译型和解释型 我们先看看编译型 其实它和汇编语言是一样的 也是有一个负责翻译的程序来对我们的源代码进行转换 生成相对应的可执行代码 这个过程说得专业一点 就称为编译 Compile 而负责编译的程序自然就称为编译器 Compiler 如果
  • Python day04 作业

    数学方面 五角星 一个五角星被定义为n 3n 1 2 def getPentagalNumber n c n 3 n 1 2 if n 10 0 print c end else print for i in range 1 101 get
  • Ubuntu在安装snappy时出现CMake Error at CMakeLists.txt:300 (set_property): set_property could not find TA

    在Ubuntu安装snappy过程中 出现了如下问题提示 这个要怎么解决 求各位大神解答 CMake Error at CMakeLists txt 294 add subdirectory The source directory hom
  • 华为OD机试 - 计算礼品发放的最小分组数目(Java)

    题目描述 又到了一年的末尾 项目组让小明负责新年晚会的小礼品发放工作 为使得参加晚会的同事所获得的小礼品价值相对平衡 需要把小礼品根据价格进行分组 但每组最多只能包括两件小礼品 并且每个分组的价格总和不能超过一个价格上限 为了保证发放小礼品
  • 小试牛刀1:使用Python-OpenCV 实现一副图片的高斯模糊处理

    实验步骤 1 环境 安装好python3 x opencv3 3 window下 2 高斯模糊 概念 高斯模糊本质上是低通滤波器 输出图像的每个像素点是原图像上对应像素点与周围像素点的加权和 使用cv2做高斯模糊 只要一行代码调用Gauss
  • 微信小程序页面栈_小程序页面栈详解

    在做小程序项目的时候不难发现 使用navigateTo进行页面跳转后 点击左上角或使用navigateBack返回 总是会按照之前的页面进入倒序来展示页面 那么问题来了 它们的跳转规则是什么样的呢 结合到实际业务中如何灵活运用呢 什么是页面
  • No SOURCES given to target: xxx

    文章目录 一 问题描述 二 解决办法 一 问题描述 CMake Error at CMakeLists txt add executable Cannot find source file src rs capture cpp Tried
  • 关于搭建简易广域网私人通信程序(python)一步到位!

    原料 python3 腾讯云服务器 用到的库 socket sys threading time pyinstaller 除pyinstaller外均不需单独安装 首先 默认已经买好云服务器 且安装好了python3 此处使用腾讯云服务器
  • csv文件的读与写

    csv文件的读取与写入 1 csv文件的读取 import pandas as pd csv path dataA1 csv df pd read csv csv path 可以通过csv文件的表头读取出某一列 表头见下图 print it
  • 理解inode

    inode是一个重要概念 是理解Unix Linux文件系统和硬盘储存的基础 我觉得 理解inode 不仅有助于提高系统操作水平 还有助于体会Unix设计哲学 即如何把底层的复杂性抽象成一个简单概念 从而大大简化用户接口 下面就是我的ino
  • 华为OD机试真题-基站维护最短距离 【2023.Q1】

    参考代码 小王是一名基站维护工程师 负责某区域的基站维护 某地方有n个基站 1
  • Android中的签名和签名文件的生成过程

    一 概述 二 还是从Key Store和keytool说起吧 三 数字签名和数字证书 四 apk的签名过程 五 签名中 MANIFEST MF CERT SF和 CERT RSA是怎么生成的 1 MANIFEST MF 2 CERT SF
  • QT日志系统创建,读取,修复

    一 内容简介 构建QT日志系统 遇到的问题以及结局办法 读取日志文件 用于检查程序运行情况 并且修复异常数据 二 软件环境 2 1 QT 5 14 1 新版QT6 4 6 5在线安装经常失败 而5 9版本又无法编译64位程序 所以就采用5
  • 巧用千寻位置GNSS软件

    千寻位置GNSS软件中的CAD功能 用于已有 CAD的图形的导入和编辑 并且可以对 CAD图形已有线条进行线放样 在日常测绘工作中十分常见 下面向各位介绍CAD功能的使用技巧 点击 测量 gt CAD 进入 CAD功能如图 5 3 1所示
  • 显卡无法为此计算机,如何解决win10系统电脑中无法安装intel显卡驱动的问题

    如何解决win10系统电脑中无法安装intel显卡驱动的问题 腾讯视频 爱奇艺 优酷 外卖 充值4折起 在使用win10系统电脑的时候 如果我们想要安装intel显卡驱动 却提示无法安装的话 应如何处理呢 接下来就由小编来告诉大家 一 手动
  • CentOS7(Linux)安装总结

    主要参考以下文章 CentOS7 Linux 详细安装教程 图文详解 缄默 給 傷的博客 CSDN博客 linuxcentos7安装步骤https blog csdn net weixin 43849575 article details
  • Mutex内核同步机制详解

    一 Mutex锁简介 在linux内核中 互斥量 mutex 即mutual exclusion 是一种保证串行化的睡眠锁机制 和spinlock的语义类似 都是允许一个执行线索进入临界区 不同的是当无法获得锁的时候 spinlock原地自
  • 使用VNC远程桌面Ubuntu【内网穿透实现公网远程】

    文章目录 前言 1 ubuntu安装VNC 2 设置vnc开机启动 3 windows 安装VNC viewer连接工具 4 内网穿透 4 1 安装cpolar 支持使用一键脚本命令安装 4 2 创建隧道映射 4 3 测试公网远程访问 5
  • 【深度学习】 Python 和 NumPy 系列教程(十五):Matplotlib详解:2、3d绘图类型(1):线框图(Wireframe Plot)

    目录 一 前言 二 实验环境 三 Matplotlib详解 1 2d绘图类型 2 3d绘图类型 0 设置中文字体 1 线框图 Wireframe Plot 一 前言 Python是一种高级编程语言 由Guido van Rossum于199
  • Qt事件过滤器

    有时候 对象需要查看 甚至要拦截发送到另外对象的事件 例如 对话框可能想要拦截按键事件 不让别的组件接收到 或者要修改回车键的默认处理 通过前面的章节 我们已经知道 Qt 创建了 QEvent 事件对象之后 会调用 QObject 的 ev