当前位置: 首页 > news >正文

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 事件传递
  • 对于同步事件
  1. 使用 QCoreApplication::sendEvent() 方法时,事件会被立即发送给接收者。

  2. 发送事件的线程会等待,直到事件被完全处理。

  • 对于异步事件
  1. 使用 QCoreApplication::postEvent() 方法时,生成的事件并非被立即处理,而是被放入目标对象所属线程的事件队列中,等待调度。

  2. QCoreApplication::exec() 启动的主事件循环会从队列中取出事件进行处理(非阻塞),并通过 QCoreApplication::notify() 方法来分发该事件到目标对象(事件通知),确保每个事件都能被正确地发生给它的接收者。

  3. 在事件被传递给目标对象之前,如果有安装事件过滤器,首先会调用这些过滤器的 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 中&#xff0c;所有事件都继承自 QEvent &#xff0c;并且每个事件都有特定的标识符&#xff0c;如&#xff1a;Qt::MouseButtonPress 代表鼠标按下事件。 每个事件对象包含该事件的所有相关信息&#xff…...

DeepSeek相关技术整理

相关介绍 2024年12月26日&#xff0c;DeepSeek V3模型发布&#xff08;用更低的训练成本&#xff0c;训练出更好的效果&#xff09;671B参数&#xff0c;激活37B。2025年1月20日&#xff0c;DeepSeek-R1模型发布&#xff08;仅需少量标注数据&#xff08;高质量长cot&#xff…...

DeepSeek 遭 DDoS 攻击背后:DDoS 攻击的 “千层套路” 与安全防御 “金钟罩”

当算力博弈升级为网络战争&#xff1a;拆解DDoS攻击背后的技术攻防战——从DeepSeek遇袭看全球网络安全新趋势 在数字化浪潮席卷全球的当下&#xff0c;网络已然成为人类社会运转的关键基础设施&#xff0c;深刻融入经济、生活、政务等各个领域。从金融交易的实时清算&#xf…...

蓝桥杯之c++入门(二)【输入输出(上)】

目录 前言1&#xff0e;getchar和 putchar1.1 getchar()1.2 putchar() 2&#xff0e;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&#xff1a…...

消息队列应用示例MessageQueues-STM32CubeMX-FreeRTOS《嵌入式系统设计》P343-P347

消息队列 使用信号量、事件标志组和线标志进行任务同步时&#xff0c;只能提供同步的时刻信息&#xff0c;无法在任务之间进行数据传输。要实现任务间的数据传输&#xff0c;一般使用两种方式&#xff1a; 1. 全局变量 在 RTOS 中使用全局变量时&#xff0c;必须保证每个任务…...

算法题(55):用最少数量的箭引爆气球

审题&#xff1a; 本题需要我们找到最少需要的箭数&#xff0c;并返回 思路: 首先我们需要把本题描述的问题理解准确 &#xff08;1&#xff09;arrow从x轴任一点垂直射出 &#xff08;2&#xff09;一旦射出&#xff0c;无限前进 也就是说如果气球有公共区域&#xff08;交集&…...

谭浩强C语言程序设计(4) 8章(下)

1、输入三个字符串按照字母顺序从小到大输出 #include <cstdio> // 包含cstdio头文件&#xff0c;用于输入输出函数 #include <cstring> // 包含cstring头文件&#xff0c;用于字符串处理函数#define N 20 // 定义字符串的最大长度为20// 函数&#xff1a;…...

AlexNet论文代码阅读

论文标题&#xff1a; ImageNet Classification with Deep Convolutional Neural Networks 论文链接&#xff1a; https://volctracer.com/w/BX18q92F 代码链接&#xff1a; https://github.com/dansuh17/alexnet-pytorch 内容概述 训练了一个大型的深度卷积神经网络&#xf…...

62.病毒在封闭空间中的传播时间|Marscode AI刷题

1.题目 问题描述 在一个封闭的房间里摆满了座位&#xff0c;每个座位东西向和南北向都有固定 1 米的间隔。座位上坐满了人&#xff0c;坐着的人可能带了口罩&#xff0c;也可能没有带口罩。我们已经知道房间里的某个人已经感染了病毒&#xff0c;病毒的传播速度是每秒钟感染距…...

Elixir语言的安全开发

Elixir语言的安全开发 引言 在当今这个互联网高度发展的时代&#xff0c;软件的安全性变得越来越重要。随着网络攻击的增多&#xff0c;软件漏洞的频繁暴露&#xff0c;开发者面临着前所未有的安全挑战。Elixir&#xff0c;作为一种现代化的函数式编程语言&#xff0c;以其高…...

Rust 条件语句

Rust 条件语句 在编程语言中&#xff0c;条件语句是进行决策和实现分支逻辑的关键。Rust 语言作为一门系统编程语言&#xff0c;其条件语句的使用同样至关重要。本文将详细介绍 Rust 中的条件语句&#xff0c;包括其基本用法、常见场景以及如何避免常见错误。 基本用法 Rust…...

小红的合数寻找

A-小红的合数寻找_牛客周赛 Round 79 题目描述 小红拿到了一个正整数 x&#xff0c;她希望你在 [x,2x] 区间内找到一个合数&#xff0c;你能帮帮她吗&#xff1f; 一个数为合数&#xff0c;当且仅当这个数是大于1的整数&#xff0c;并且不是质数。 输入描述 在一行上输入一…...

使用等宽等频法进行数据特征离散化

在数据分析与处理的过程中,特征离散化是一种常见的操作。通过将连续的数值型数据转换为离散类别,能够更好地处理数据,尤其是在机器学习模型中进行分类问题的建模时。离散化能够简化数据结构,减少数据噪声,并提高模型的解释性。 本文将详细介绍如何使用 pandas 库中的 cut…...

解析 Oracle 中的 ALL_SYNONYMS 和 ALL_VIEWS 视图:查找同义词与视图的基础操作

目录 前言1. ALL_SYNONYMS 视图2. ALL_VIEWS 视图3. 扩展 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF 1. ALL_SYNONYMS 视图 在 Oracle 数据库中&#xff0c;同义词&#xff08;Synonym&#xff09;是对数…...

AI协助探索AI新构型的自动化创新概念

训练AI自生成输出模块化代码&#xff0c;生成元代码级别的AI功能单元代码&#xff0c;然后再由AI组织为另一个AI&#xff0c;实现AI开发AI的能力&#xff1b;用AI协助探索迭代新构型AI将会出现&#xff0c;并成为一种新的技术路线潮流。 有限结点&#xff0c;无限的连接形式&a…...

从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(OLED设备层封装)

目录 OLED设备层驱动开发 如何抽象一个OLED 完成OLED的功能 初始化OLED 清空屏幕 刷新屏幕与光标设置1 刷新屏幕与光标设置2 刷新屏幕与光标设置3 绘制一个点 反色 区域化操作 区域置位 区域反色 区域更新 区域清空 测试我们的抽象 整理一下&#xff0c;我们应…...

【Redis】Redis 经典面试题解析:深入理解 Redis 的核心概念与应用

Redis 是一个高性能的键值存储系统&#xff0c;广泛应用于缓存、消息队列、排行榜等场景。在面试中&#xff0c;Redis 是一个高频话题&#xff0c;尤其是其核心概念、数据结构、持久化机制和高可用性方案。 1. Redis 是什么&#xff1f;它的主要特点是什么&#xff1f; 答案&a…...

TensorFlow 示例摄氏度到华氏度的转换(一)

TensorFlow 实现神经网络模型来进行摄氏度到华氏度的转换&#xff0c;可以将其作为一个回归问题来处理。我们可以通过神经网络来拟合这个简单的转换公式。 1. 数据准备与预处理 2. 构建模型 3. 编译模型 4. 训练模型 5. 评估模型 6. 模型应用与预测 7. 保存与加载模型 …...

7.DP算法

DP 在C中&#xff0c;动态规划&#xff08;Dynamic Programming&#xff0c;DP&#xff09;是一种通过将复杂问题分解为重叠子问题来高效求解的算法设计范式。以下是DP算法的核心要点和实现方法&#xff1a; 一、动态规划的核心思想 重叠子问题&#xff1a;问题可分解为多个重…...

Baklib构建高效协同的基于云的内容中台解决方案

内容概要 随着云计算技术的飞速发展&#xff0c;内容管理的方式也在不断演变。企业面临着如何在数字化转型过程中高效管理和协同处理内容的新挑战。为应对这些挑战&#xff0c;引入基于云的内容中台解决方案显得尤为重要。 Baklib作为创新型解决方案提供商&#xff0c;致力于…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖

在Vuzix M400 AR智能眼镜的助力下&#xff0c;卢森堡罗伯特舒曼医院&#xff08;the Robert Schuman Hospitals, HRS&#xff09;凭借在无菌制剂生产流程中引入增强现实技术&#xff08;AR&#xff09;创新项目&#xff0c;荣获了2024年6月7日由卢森堡医院药剂师协会&#xff0…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...