Qt事件处理:理解处理器、过滤器与事件系统
1. 事件
事件 是一个描述应用程序中、发生的某些事情的对象。
在 Qt 中,所有事件都继承自 QEvent ,并且每个事件都有特定的标识符,如:Qt::MouseButtonPress 代表鼠标按下事件。
每个事件对象包含该事件的所有相关信息,如:鼠标事件包含鼠标的坐标、按下的按钮等信息。
2. 事件处理器
事件处理器 是用于处理特定类型事件的成员函数,通常以 event 结尾,如:mousePressEvent 、enterEvent 等。
事件处理器定义了当某个事件发生时,应执行的操作。
事件处理器可以分为两类:
- 预定义事件处理器:由 Qt 提供的标准事件处理函数,可以通过重写它们以实现自定义行为。
class SessionFriendItem : public QWidget
{Q_OBJECT
public:SessionFriendItem(QWidget* owner, const QIcon& avatar, const QString& name, const QString& text): owner(owner), selected(false){// 1. 设置基本属性和样式this->setFixedHeight(64);this->setStyleSheet("QWidget { background-color: rgb(236, 233, 231); }");// 2. 创建网格布局QGridLayout* layout = new QGridLayout();layout->setContentMargins(0, 0, 0, 0);layout->setVerticalSpacing(0); // 设置竖直方向间距layout->setHorizontalSpacing(0); // 设置水平方向间距this->setLayout(layout);// 3. 创建头像QPushButton avatar_btn = new QPushButton();avatar_btn->setFixedSize(QSize(46, 46));avatar_btn->setIconSize(QSize(46, 46));avatar_btn->setIcon(avatar);avatar_btn->setStyleSheet("QPushButton { border: none; background-color: transparent; }");layout->addWidget(avatar_btn, 0, 0, 2, 2);// 4. 创建昵称QLabel* name_label = new QLabel();name_label->setText(name);name_label->setFixedHeight(30);name_label->setStyleSheet("QLabel { font-size: 14px; }");layout->addWidget(name_label, 0, 2, 1, 6);// 5. 添加预览消息QLabel* msg_label = new QLabel();msg_label->setText(text);msg_label->setFixedHeight(25);msg_label->setStyleSheet("QLabel { font-size: 12px; }");layout->addWidget(msg_label, 1, 2, 1, 6);}void mousePressEvent(QMouseEvent* event) override{// 1. 恢复兄弟组件的 rgbQObjectList* children = this->parent()->children();for (QObject* child : children){if (child->isWidgetType() == false) continue;SessionFriendItem* temp = dynamic_cast<SessionFriendItem*>(child);if (temp->selected == true){temp->selected = false;temp->setStyleSheet("QWidget { background-color: rgb(236, 233, 231); }");}}// 2. 设置当前组件的 rgbthis->selected = true;this->setStyleSheet("QWidget { background-color: rgb(200, 199, 198); }");}void enterEvent(QEnterEvent* event) override{// 当前组件被点击,则不处理if (selected == true) return; this->setStyleSheet("QWidget { background-color: rgb(222, 220, 218); }");}void leaveEvent(QEvent* event) override{if (selected == true) return;this->setStyleSheet("QWidget { background-color: rgb(236, 233, 231); }");}
private:QWidget* owner;bool selected;
};

- 自定义事件处理器:处理一些特殊类型的事件,可以通过事件过滤器或子类化 QObject 来实现。
3. 事件过滤器
在 Qt 中,事件过滤器(eventFilter)提供了一种机制,允许一个对象 监视并处理 另一个对象的事件。
3.1 基本概念
事件过滤器允许拦截发送给某个对象的所有事件,并在这些事件被该对象处理之前,决定如何处理它们。
步骤:
- 安装事件过滤器:通过调用
installEventFilter()方法,将一个对象设置为另一个对象的事件过滤器。 - 重写
eventFilter()函数:在作为事件过滤器的对象中,重写bool eventFilter(QObject* obj, QEvent* event)函数,来定义具体的事件处理逻辑。
3.2 工作原理
QMainWindow不能直接设置布局,需要通过中央部件来管理布局。
this->setCentralWidget()
// mainwindow.h
class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();bool eventFilter(QObject* object, QEvent* event) override;QWidget* mainWidget;QPushButton* button;private:Ui::MainWindow *ui;
};// mainwindow.cpp
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);mainWidget = new QWidget(this);this->setCentralWidget(mainWidget);QVBoxLayout* layout = new QVBoxLayout();mainWidget->setLayout(layout);button = new QPushButton();button->setText("点击");button->setFixedSize(QSize(50, 50));layout->addWidget(button);// 安装事件过滤器button->installEventFilter(this);
}bool MainWindow::eventFilter(QObject* object, QEvent* event)
{if (object == button){if (event->type() == QEvent::MouseButtonPress){qDebug() << "Button_Press";}else if (event->type() == QEvent::Enter){qDebug() << "Button_Enter";}else if (event->type() == QEvent::Leave){qDebug() << "Button_Leave";}// return false; // 允许事件继续传递return true;}// 交给其它事件处理器处理return QMainWindow::eventFilter(object, event);
}
鼠标进入按钮上方,鼠标点击按钮,鼠标离开按钮

installEventFilter 的作用目标
-
事件过滤器的本质:当一个对象 A 调用 installEventFilter(B) ,意味着对象 B 会优先接收到对象 A 的事件,并可以通过 eventFilter() 方法拦截或处理这些事件。
-
如果希望在事件滤波器 B 处理完事件后,仍然让目标对象 A 继续处理该事件,可以在事件滤波器逻辑的末尾 return false。这样,事件会继续按照正常的事件处理流程传递下去。
-
自定义类 能够作为事件过滤器、并被目标对象设置,需要确保该类重载了 eventfilter() 方法;原生的 Qt 对象(如 QWidget)无法直接担任事件过滤器的角色,因为它们没有提供对 eventfilter() 的重载接口。
4. 事件系统
Qt 的事件系统基于事件驱动模型工作,其核心是通过事件队列(Event Queue)实现异步调用。
以下是其基本运作流程:
4.1 事件产生
当用户与应用程序进行交互,或系统内部发生某些变化,就会产生相应的事件。
所有事件均封装为 QEvent 的子类对象。
例如,用户按下鼠标左键,会产生一个 QMouseEvent 对象,该对象包含了关于鼠标点击的所有信息,包括点击的位置、按钮的状态等;
键盘按键的按下或释放会产生 QKeyEvent 对象。
4.2 事件传递
- 对于同步事件:
-
使用
QCoreApplication::sendEvent()方法时,事件会被立即发送给接收者。 -
发送事件的线程会等待,直到事件被完全处理。
- 对于异步事件:
-
使用
QCoreApplication::postEvent()方法时,生成的事件并非被立即处理,而是被放入目标对象所属线程的事件队列中,等待调度。 -
QCoreApplication::exec() 启动的主事件循环会从队列中取出事件进行处理(非阻塞),并通过 QCoreApplication::notify() 方法来分发该事件到目标对象(事件通知),确保每个事件都能被正确地发生给它的接收者。
-
在事件被传递给目标对象之前,如果有安装事件过滤器,首先会调用这些过滤器的 eventFilter() 方法;如果该事件没有被过滤器拦截,则继续传递给目标对象。
4.3 事件处理
通过重写 event() 方法,或特定的事件处理器(如 mousePressEvent() ),实现业务逻辑。
如果事件未被处理(如未重写 event() 或未调用基类实现),某些对象会向父对象传递(冒泡机制),直至顶层对象。
事件是否传递取决于事件类型和 accept() / ignore() 的标记。
QMouseEvent 默认 accept() ,QKeyEvent() 默认 ignore() ,QPaintEvent 仅在目标对象处理、不会传递。
void MainWindow::mousePressEvent(QMouseEvent* event)
{qDebug() << "button is pressed";event->accept(); // 标记事件已处理// event->ignore(); // 允许事件继续传递
}
4.4 事件结束
事件对象会在处理完成后,由 Qt 自动销毁;除非事件被通过 deleteLater() 标记为 deferred delete。
相关文章:
Qt事件处理:理解处理器、过滤器与事件系统
1. 事件 事件 是一个描述应用程序中、发生的某些事情的对象。 在 Qt 中,所有事件都继承自 QEvent ,并且每个事件都有特定的标识符,如:Qt::MouseButtonPress 代表鼠标按下事件。 每个事件对象包含该事件的所有相关信息ÿ…...
DeepSeek相关技术整理
相关介绍 2024年12月26日,DeepSeek V3模型发布(用更低的训练成本,训练出更好的效果)671B参数,激活37B。2025年1月20日,DeepSeek-R1模型发布(仅需少量标注数据(高质量长cotÿ…...
DeepSeek 遭 DDoS 攻击背后:DDoS 攻击的 “千层套路” 与安全防御 “金钟罩”
当算力博弈升级为网络战争:拆解DDoS攻击背后的技术攻防战——从DeepSeek遇袭看全球网络安全新趋势 在数字化浪潮席卷全球的当下,网络已然成为人类社会运转的关键基础设施,深刻融入经济、生活、政务等各个领域。从金融交易的实时清算…...
蓝桥杯之c++入门(二)【输入输出(上)】
目录 前言1.getchar和 putchar1.1 getchar()1.2 putchar() 2.scanf和 printf2.1 printf2.1.1基本用法2.1.2占位符2.1.3格式化输出2.1.3.1 限定宽度2.1.3.2 限定小数位数 2.2 scanf2.2.1基本用法2.2.2 占位符2.2.3 scanf的返回值 2.3练习练习1:…...
消息队列应用示例MessageQueues-STM32CubeMX-FreeRTOS《嵌入式系统设计》P343-P347
消息队列 使用信号量、事件标志组和线标志进行任务同步时,只能提供同步的时刻信息,无法在任务之间进行数据传输。要实现任务间的数据传输,一般使用两种方式: 1. 全局变量 在 RTOS 中使用全局变量时,必须保证每个任务…...
算法题(55):用最少数量的箭引爆气球
审题: 本题需要我们找到最少需要的箭数,并返回 思路: 首先我们需要把本题描述的问题理解准确 (1)arrow从x轴任一点垂直射出 (2)一旦射出,无限前进 也就是说如果气球有公共区域(交集&…...
谭浩强C语言程序设计(4) 8章(下)
1、输入三个字符串按照字母顺序从小到大输出 #include <cstdio> // 包含cstdio头文件,用于输入输出函数 #include <cstring> // 包含cstring头文件,用于字符串处理函数#define N 20 // 定义字符串的最大长度为20// 函数:…...
AlexNet论文代码阅读
论文标题: ImageNet Classification with Deep Convolutional Neural Networks 论文链接: https://volctracer.com/w/BX18q92F 代码链接: https://github.com/dansuh17/alexnet-pytorch 内容概述 训练了一个大型的深度卷积神经网络…...
62.病毒在封闭空间中的传播时间|Marscode AI刷题
1.题目 问题描述 在一个封闭的房间里摆满了座位,每个座位东西向和南北向都有固定 1 米的间隔。座位上坐满了人,坐着的人可能带了口罩,也可能没有带口罩。我们已经知道房间里的某个人已经感染了病毒,病毒的传播速度是每秒钟感染距…...
Elixir语言的安全开发
Elixir语言的安全开发 引言 在当今这个互联网高度发展的时代,软件的安全性变得越来越重要。随着网络攻击的增多,软件漏洞的频繁暴露,开发者面临着前所未有的安全挑战。Elixir,作为一种现代化的函数式编程语言,以其高…...
Rust 条件语句
Rust 条件语句 在编程语言中,条件语句是进行决策和实现分支逻辑的关键。Rust 语言作为一门系统编程语言,其条件语句的使用同样至关重要。本文将详细介绍 Rust 中的条件语句,包括其基本用法、常见场景以及如何避免常见错误。 基本用法 Rust…...
小红的合数寻找
A-小红的合数寻找_牛客周赛 Round 79 题目描述 小红拿到了一个正整数 x,她希望你在 [x,2x] 区间内找到一个合数,你能帮帮她吗? 一个数为合数,当且仅当这个数是大于1的整数,并且不是质数。 输入描述 在一行上输入一…...
使用等宽等频法进行数据特征离散化
在数据分析与处理的过程中,特征离散化是一种常见的操作。通过将连续的数值型数据转换为离散类别,能够更好地处理数据,尤其是在机器学习模型中进行分类问题的建模时。离散化能够简化数据结构,减少数据噪声,并提高模型的解释性。 本文将详细介绍如何使用 pandas 库中的 cut…...
解析 Oracle 中的 ALL_SYNONYMS 和 ALL_VIEWS 视图:查找同义词与视图的基础操作
目录 前言1. ALL_SYNONYMS 视图2. ALL_VIEWS 视图3. 扩展 前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 1. ALL_SYNONYMS 视图 在 Oracle 数据库中,同义词(Synonym)是对数…...
AI协助探索AI新构型的自动化创新概念
训练AI自生成输出模块化代码,生成元代码级别的AI功能单元代码,然后再由AI组织为另一个AI,实现AI开发AI的能力;用AI协助探索迭代新构型AI将会出现,并成为一种新的技术路线潮流。 有限结点,无限的连接形式&a…...
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(OLED设备层封装)
目录 OLED设备层驱动开发 如何抽象一个OLED 完成OLED的功能 初始化OLED 清空屏幕 刷新屏幕与光标设置1 刷新屏幕与光标设置2 刷新屏幕与光标设置3 绘制一个点 反色 区域化操作 区域置位 区域反色 区域更新 区域清空 测试我们的抽象 整理一下,我们应…...
【Redis】Redis 经典面试题解析:深入理解 Redis 的核心概念与应用
Redis 是一个高性能的键值存储系统,广泛应用于缓存、消息队列、排行榜等场景。在面试中,Redis 是一个高频话题,尤其是其核心概念、数据结构、持久化机制和高可用性方案。 1. Redis 是什么?它的主要特点是什么? 答案&a…...
TensorFlow 示例摄氏度到华氏度的转换(一)
TensorFlow 实现神经网络模型来进行摄氏度到华氏度的转换,可以将其作为一个回归问题来处理。我们可以通过神经网络来拟合这个简单的转换公式。 1. 数据准备与预处理 2. 构建模型 3. 编译模型 4. 训练模型 5. 评估模型 6. 模型应用与预测 7. 保存与加载模型 …...
7.DP算法
DP 在C中,动态规划(Dynamic Programming,DP)是一种通过将复杂问题分解为重叠子问题来高效求解的算法设计范式。以下是DP算法的核心要点和实现方法: 一、动态规划的核心思想 重叠子问题:问题可分解为多个重…...
Baklib构建高效协同的基于云的内容中台解决方案
内容概要 随着云计算技术的飞速发展,内容管理的方式也在不断演变。企业面临着如何在数字化转型过程中高效管理和协同处理内容的新挑战。为应对这些挑战,引入基于云的内容中台解决方案显得尤为重要。 Baklib作为创新型解决方案提供商,致力于…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
