Qt事件处理机制2-事件函数的传播
所有继承自QObject的类都有event函数,该函数用来处理自身的事件,函数定义如下:
virtual bool QObject::event(QEvent *e);
Qt帮助文档:
This virtual function receives events to an object and should return true if the event e recognized and processed. The event() function can be reimplemented to customize the behavior of an object. Make sure you call the parent event class implementation for all the events you did not handle.
大致意思:在event函数中,当事件被识别并处理后,如果返回true,表示该event函数执行结束,不再希望执行具体的事件处理函数,例如mousePressEvent、paintEvent等;如果返回false,也表示该event函数执行结束,不再希望执行具体的事件处理函数,但事件会向上传递,即传递给父组件,进入父组件的event函数。也可以event函数中调用父类的event函数,交给父类来处理,父类仍旧遵循以上规则。
注:当event函数中返回true之前,若已经设置了e->ignore(),仍旧会调用父组件的event函数;只有当event函数返回true,并且e->isAccepted()也为true的时候,才不再调用父组件的event函数。QEvent *e的默认值是true,除非在eventFilter函数中设置为false。
下面关于文档里说的返回值,进行演示说明
MyButton.h
#ifndef MYBUTTON_H
#define MYBUTTON_H#include <QPushButton>class MyButton : public QPushButton
{Q_OBJECT
public:MyButton(QWidget *parent = nullptr);~MyButton();protected:bool event(QEvent *e) override;
};#endif // MYBUTTON_H
MyButton.cpp
#include "MyButton.h"
#include <QDebug>
#include <QEvent>MyButton::MyButton(QWidget *parent) : QPushButton(parent){}MyButton::~MyButton(){}bool MyButton::event(QEvent *e)
{if (e->type() == QEvent::MouseButtonPress){qDebug() << __FUNCTION__ << event->isAccepted();return true;}return QPushButton::event(e);
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();protected:bool event(QEvent *e) override;private:Ui::MainWindow *ui;
};#endif // MAINWINDOW_H
MainWindow.cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QDebug>
#include <QEvent>
#include <QMouseEvent>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);
}MainWindow::~MainWindow()
{delete ui;
}bool MainWindow::event(QEvent *e)
{if (e->type() == QEvent::MouseButtonPress){qDebug() << __FUNCTION__ << e->isAccepted();}return QMainWindow::event(e);
}
鼠标点击MyButton类按钮,运行结果: 事件向父类传播
// 情形1:直接return false
bool MyButton::event(QEvent *e)
{if (e->type() == QEvent::MouseButtonPress){qDebug() << __FUNCTION__ << event->isAccepted();return false;}return QPushButton::event(e);
}// 情形2:e->ignore()后return true
bool MyButton::event(QEvent *e)
{if (e->type() == QEvent::MouseButtonPress){qDebug() << __FUNCTION__ << event->isAccepted();e->ignore();return true;}return QPushButton::event(e);
}// 运行结果都如下:
MyButton::event true
MainWindow::event true
鼠标点击MyButton类按钮,运行结果: 事件停止向父类传播
// 情形3:直接return true
bool MyButton::event(QEvent *e)
{if (e->type() == QEvent::MouseButtonPress){qDebug() << __FUNCTION__ << event->isAccepted();return true;}return QPushButton::event(e);
}// 情形3:返回父类event函数的处理结果
bool MyButton::event(QEvent *e)
{if (e->type() == QEvent::MouseButtonPress){qDebug() << __FUNCTION__ << event->isAccepted();}return QPushButton::event(e);
}// 运行结果都如下:
MyButton::event true
补充1:QT源码中事件处理过程中调用函数如下:
QApplication::exec()QCoreApplication::exec()QEventLoop::exec(ProcessEventsFlags )QEventLoop::processEvents(ProcessEventsFlags )QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags)QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)bool QETWidget::translateMouseEvent(const MSG &msg)bool QApplicationPrivate::sendMouseEvent(...)inline bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)bool QApplication::notify(QObject *receiver, QEvent *e)bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)bool QWidget::event(QEvent *event)
补充2:notify函数中处理事件传播
notify函数中处理事件传播的时候,会调用notify_helper函数,当(res && eventAccepted)为真时停止向父类传播,否则w = w->parentWidget(),进而调用父类的notify_helper函数,而notify_helper函数中会调用receiver->event(e)函数。
bool QApplication::notify(QObject *receiver, QEvent *e)
{QWidget* w = static_cast<QWidget *>(receiver);QMouseEvent* mouse = static_cast<QMouseEvent*>(e);QPoint relpos = mouse->pos();...switch (e->type()) {...case QEvent::MouseButtonPress:case QEvent::MouseButtonRelease:case QEvent::MouseButtonDblClick:case QEvent::MouseMove:{...bool eventAccepted = mouse->isAccepted();QPointer<QWidget> pw = w;while (w) {QMouseEvent me(mouse->type(), relpos, mouse->windowPos(), mouse->globalPos(),mouse->button(), mouse->buttons(), mouse->modifiers(), mouse->source());me.spont = mouse->spontaneous();me.setTimestamp(mouse->timestamp());QGuiApplicationPrivate::setMouseEventFlags(&me, mouse->flags());// throw away any mouse-tracking-only mouse eventsif (!w->hasMouseTracking()&& mouse->type() == QEvent::MouseMove && mouse->buttons() == 0) {// but still send them through all application event filters (normally done by notify_helper)d->sendThroughApplicationEventFilters(w, w == receiver ? mouse : &me);res = true;} else {w->setAttribute(Qt::WA_NoMouseReplay, false);res = d->notify_helper(w, w == receiver ? mouse : &me);e->spont = false;}eventAccepted = (w == receiver ? mouse : &me)->isAccepted();if (res && eventAccepted)break;if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))break;relpos += w->pos();w = w->parentWidget();}...}...
}
bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
{// These tracepoints (and the whole function, actually) are very similar// to the ones in QCoreApplicationPrivate::notify_helper; the reason for their// duplication is because tracepoint symbols are not exported by QtCore.// If you adjust the tracepoints here, consider adjusting QCoreApplicationPrivate too.Q_TRACE(QApplication_notify_entry, receiver, e, e->type());bool consumed = false;bool filtered = false;Q_TRACE_EXIT(QApplication_notify_exit, consumed, filtered);// send to all application event filtersif (threadRequiresCoreApplication()&& receiver->d_func()->threadData->thread == mainThread()&& sendThroughApplicationEventFilters(receiver, e)) {filtered = true;return filtered;}if (receiver->isWidgetType()) {QWidget *widget = static_cast<QWidget *>(receiver);#if !defined(QT_NO_CURSOR)// toggle HasMouse widget state on enter and leaveif ((e->type() == QEvent::Enter || e->type() == QEvent::DragEnter) &&(!QApplication::activePopupWidget() || QApplication::activePopupWidget() == widget->window()))widget->setAttribute(Qt::WA_UnderMouse, true);else if (e->type() == QEvent::Leave || e->type() == QEvent::DragLeave)widget->setAttribute(Qt::WA_UnderMouse, false);
#endifif (QLayout *layout=widget->d_func()->layout) {layout->widgetEvent(e);}}// send to all receiver event filtersif (sendThroughObjectEventFilters(receiver, e)) {filtered = true;return filtered;}// deliver the eventconsumed = receiver->event(e);QCoreApplicationPrivate::setEventSpontaneous(e, false);return consumed;
}
注: event函数中调用e->ignore()之后,父对象的event函数中e->isAccepted()值仍然为true的原因是每一次调用notify_helper函数时,传递的事件e都是临时的。
QMouseEvent* mouse = static_cast<QMouseEvent*>(e);
...
QMouseEvent me(mouse->type(), relpos, mouse->windowPos(), mouse->globalPos(), mouse->button(), mouse->buttons(), mouse->modifiers(), mouse->source());
...
res = d->notify_helper(w, w == receiver ? mouse : &me);
注: 补充1的内容引自QT QEvent 事件调用的来龙去脉,作者:QtC++ 开发从业者
相关文章:
Qt事件处理机制2-事件函数的传播
所有继承自QObject的类都有event函数,该函数用来处理自身的事件,函数定义如下: virtual bool QObject::event(QEvent *e);Qt帮助文档: This virtual function receives events to an object and should return true i…...
【PDF.js】PDF文件预览
【PDF.js】PDF文件预览 一、PDF.js二、PDF.js 下载1、下载PDF.js2、在项目中引入3、屏蔽跨域错误 三、项目中使用四、说明五、实现效果 使用PDFJS实现pdf文件的预览,支持预览指定页、关键词搜索、缩略图、页面尺寸调整等等。 一、PDF.js 官方地址 文档地址 二、PD…...
从建表语句带你学习doris_表索引
1、doris建表概述 1.1、doris建表模板 CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [DATABASE.]table_name (column_definition1[,column_deinition2,......][,index_definition1,[,index_definition2,]] ) [ENGINE [olap|mysql|broker|hive]] [key_desc] [COMMENT "tabl…...
Linux CentOS 安装 MySQL 服务教程
Linux CentOS 安装 MySQL 服务教程 1. 查看系统和GNU C库(glibc)版本信息 1.1 查询机器 glibc 版本信息 glibc,全名GNU C Library,是大多数Linux发行版中使用的C库,为系统和应用程序提供核心的API接口。在Linux系统中,特别是在…...
MSSQL 命令行操作说明 sql server 2022 命令行下进行配置管理
说明:本文的内容是因为我在导入Access2019的 *.accdb 格式的数据时,总是出错的背景下,不得已搜索和整理了一下,如何用命令行进行sql server 数据库和用户管理的方法,作为从Access2019 直接导出数据到sql server 数据库…...
【系统分析师】系统安全分析与设计
文章目录 1、安全基础技术1.1 密码相关1.1.1对称加密1.1.2非对称加密1.1.3信息摘要1.1.4数字签名1.1.5数字信封 1.2 PKI公钥体系 2、信息系统安全2.1 保障层次2.2 网络安全2.2.1WIFI2.2.2 网络威胁与攻击2.2.3 安全保护等级 2.3计算机病毒与木马2.4安全防范体系 1、安全基础技术…...
ActiveMQ 07 集群配置
Active MQ 07 集群配置 官方文档 http://activemq.apache.org/clustering 主备集群 http://activemq.apache.org/masterslave.html Master Slave TypeRequirementsProsConsShared File System Master SlaveA shared file system such as a SANRun as many slaves as requ…...
Redis(哨兵模式)
什么是哨兵机制 问题: redis 主从复制模式下, 一旦主节点由于故障不能提供服务, 需要人工进行主从切换, 同时大量客户端需要被通知切换到新的主节点上, 对于有一定规模的应用来说, 对于人力的资源消耗会很大.解决: 通过哨兵对主从结构进行监控, 一旦出现主节点挂了的情况, 自动…...
一种基于镜像指示位办法的RingBuffer实现,解决Mirror和2的幂个数限制
简介 在嵌入式开发中,经常有需要用到RingBuffer的概念,在RingBuffer中经常遇到一个Buffer满和Buffer空的判断的问题,一般的做法是留一个单位的buffer不用,这样做最省事,但是当RingBuffer单位是一个结构体时࿰…...
【Java开发指南 | 第十一篇】Java运算符
读者可订阅专栏:Java开发指南 |【CSDN秋说】 文章目录 算术运算符关系运算符位运算符逻辑运算符赋值运算符条件运算符(?:)instanceof 运算符Java运算符优先级 Java运算符包括:算术运算符、关系运算符、位运算符、逻辑运算符、赋值…...
【IC前端虚拟项目】验证环境方案思路和文档组织
【IC前端虚拟项目】数据搬运指令处理模块前端实现虚拟项目说明-CSDN博客 对于mvu的验证环境,从功能角度就可以分析出需要搭建哪些部分,再看一下mvu的周围环境哈: 很明显验证环境必然要包括几个部分: 1.模拟idu发送指令; 2.模拟ram/ddr读写数据; 3.rm模拟mvu的行为; …...
程序设计|C语言教学——C语言基础1:C语言的引入和入门
一、程序的执行 1.定义 解释:借助一个程序,那个程序能够试图理解你的程序,然后按照你的要求执行。下次执行的时候还需要从零开始解释。 编译:借助一个程序,能够像翻译官一样,把你的程序翻译成机器语言&a…...
初学python记录:力扣928. 尽量减少恶意软件的传播 II
题目: 给定一个由 n 个节点组成的网络,用 n x n 个邻接矩阵 graph 表示。在节点网络中,只有当 graph[i][j] 1 时,节点 i 能够直接连接到另一个节点 j。 一些节点 initial 最初被恶意软件感染。只要两个节点直接连接,…...
LlamaIndex 组件 - Storing
文章目录 一、储存概览1、概念2、使用模式3、模块 二、Vector Stores1、简单向量存储2、矢量存储选项和功能支持3、Example Notebooks 三、文件存储1、简单文档存储2、MongoDB 文档存储3、Redis 文档存储4、Firestore 文档存储 四、索引存储1、简单索引存储2、MongoDB 索引存储…...
在Linux系统中设定延迟任务
一、在系统中设定延迟任务要求如下: 要求: 在系统中建立easylee用户,设定其密码为easylee 延迟任务由root用户建立 要求在5小时后备份系统中的用户信息文件到/backup中 确保延迟任务是使用非交互模式建立 确保系统中只有root用户和easylee用户…...
JVM之方法区的详细解析
方法区 方法区:是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、即时编译器编译后的代码等数据,虽然 Java 虚拟机规范把方法区描述为堆的一个逻辑部分,但是也叫 Non-Heap(非堆) 设置方法…...
Go 使用ObjectID
ObjectID介绍 MongoDB中的ObjectId是一种特殊的12字节 BSON 类型数据,用于为主文档提供唯一的标识符,默认情况下作为 _id 字段的默认值出现在每一个MongoDB集合中的文档中。以下是ObjectId的具体组成: 1. 时间戳(Timestamp&…...
基于SpringBoot+Vue的疾病防控系统设计与实现(源码+文档+包运行)
一.系统概述 在如今社会上,关于信息上面的处理,没有任何一个企业或者个人会忽视,如何让信息急速传递,并且归档储存查询,采用之前的纸张记录模式已经不符合当前使用要求了。所以,对疾病防控信息管理的提升&a…...
2024年阿里云4核8G配置云服务器价格低性能高!
阿里云4核8G服务器租用优惠价格700元1年,配置为ECS通用算力型u1实例(ecs.u1-c1m2.xlarge)4核8G配置、1M到3M带宽可选、ESSD Entry系统盘20G到40G可选,CPU采用Intel(R) Xeon(R) Platinum处理器,阿里云优惠 aliyunfuwuqi…...
关于ContentProvider这一遍就够了
ContentProvider是什么? ContentProvider是Android四大组件之一,主要用于不同应用程序之间或者同一个应用程序的不同部分之间共享数据。它是Android系统中用于存储和检索数据的抽象层,允许不同的应用程序通过统一的接口访问数据,…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...
保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...
Linux 内存管理调试分析:ftrace、perf、crash 的系统化使用
Linux 内存管理调试分析:ftrace、perf、crash 的系统化使用 Linux 内核内存管理是构成整个内核性能和系统稳定性的基础,但这一子系统结构复杂,常常有设置失败、性能展示不良、OOM 杀进程等问题。要分析这些问题,需要一套工具化、…...
实现p2p的webrtc-srs版本
1. 基本知识 1.1 webrtc 一、WebRTC的本质:实时通信的“网络协议栈”类比 将WebRTC类比为Linux网络协议栈极具洞察力,二者在架构设计和功能定位上高度相似: 分层协议栈架构 Linux网络协议栈:从底层物理层到应用层(如…...
