QObject_event

QObject::event

QObject事件入口,所有事件的处理入口都是QObject::event和其子类的event函数

bool MyQObject::event(QEvent *e){//处理不同的事件......//处理不了的传给父对象处理return QObject::event(e);
}bool QObject::event(QEvent *e)
{switch (e->type()) {case QEvent::Timer:  //startTimer函数触发的QTimerEvent,最终走timerEvent函数处理timerEvent((QTimerEvent*)e);break;case QEvent::ChildAdded:case QEvent::ChildPolished:case QEvent::ChildRemoved:childEvent((QChildEvent*)e);break;case QEvent::DeferredDelete:qDeleteInEventHandler(this);break;case QEvent::MetaCall:  //发送信号触发关联的槽函数时(非直接调用模式),最终走QEvent::MetaCall事件调到对应的函数{QAbstractMetaCallEvent *mce = static_cast<QAbstractMetaCallEvent*>(e);if (!d_func()->connections.loadRelaxed()) {QBasicMutexLocker locker(signalSlotLock(this));d_func()->ensureConnectionData();}QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId());mce->placeMetaCall(this);//调用对应的函数break;}case QEvent::ThreadChange: {Q_D(QObject);QThreadData *threadData = d->threadData.loadRelaxed();QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.loadRelaxed();if (eventDispatcher) {QList<QAbstractEventDispatcher::TimerInfo> timers = eventDispatcher->registeredTimers(this);if (!timers.isEmpty()) {// do not to release our timer ids back to the pool (since the timer ids are moving to a new thread).eventDispatcher->unregisterTimers(this);QMetaObject::invokeMethod(this, "_q_reregisterTimers", Qt::QueuedConnection,Q_ARG(void*, (new QList<QAbstractEventDispatcher::TimerInfo>(timers))));}}break;}default:if (e->type() >= QEvent::User) {customEvent(e);break;}return false;}return true;
}

void QObject::installEventFilter(QObject *filterObj)

给对象安装一个事件过滤器即filterObj对象。
当触发事件时首先调用filterObj的eventFilter函数,判断是否过滤此事件
如果事件需要被过滤,eventFilter()函数必须返回true;否则它必须返回false。

如果在单个对象上安装了多个事件筛选器,则首先激活最后安装的筛选器。

void QObject::installEventFilter(QObject *obj)
{Q_D(QObject);if (!obj)return;//obj必须和当前对象在同一线程才能添加成功if (d->threadData != obj->d_func()->threadData) {qWarning("QObject::installEventFilter(): Cannot filter events for objects in a different thread.");return;}if (!d->extraData)d->extraData = new QObjectPrivate::ExtraData;// clean up unused items in the listd->extraData->eventFilters.removeAll((QObject*)nullptr);d->extraData->eventFilters.removeAll(obj);//这里调用prepend将事件过滤器添加到最前面d->extraData->eventFilters.prepend(obj);
}

bool eventFilter(QObject * watched, QEvent * event )

事件的处理流程就是先调用各种过滤函数,判断是否过滤,不过滤才会走到event()函数
eventFilter就是其中的一种过滤函数
返回true表示需要过滤,事件会终止不会执行
返回false表示不过滤,会继续传递事件,走到调用event()函数处理

eventFilter主要配合installEventFilter使用
eventFilter函数并不是给自己用的,正常使用一般是继承QObject实现eventFilter函数作为过滤器使用,安装在其他对象上面,帮助其他对象过滤事件

默认实现,直接返回false,表示不过滤任何事件
bool QObject::eventFilter(QObject * watched, QEvent * event )
{return false;
}
事件的处理流程
bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
{//先走全局app的事件过滤函数sendThroughApplicationEventFilters//QCoreApplication存在并且接收者在主线程中的才会走app的全局过滤函数if (QCoreApplication::self&& receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread()&& QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {filtered = true;return filtered;}// 再调用接收者安装事件过滤器的eventFilter函数,返回true将不会继续往下走调到eventif (sendThroughObjectEventFilters(receiver, event)) {filtered = true;return filtered;}//调用event函数处理事件consumed = receiver->event(event);return consumed;
}
全局app的事件过滤函数
bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event)
{//不能在主线程之外访问应用程序(app)的事件过滤器Q_ASSERT(receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread());if (extraData) {// 应用程序事件过滤器只对GUI线程中的对象调用for (int i = 0; i < extraData->eventFilters.size(); ++i) {QObject *obj = extraData->eventFilters.at(i);if (!obj)continue;//过滤器和接收者不在同一线程,直接continueif (obj->d_func()->threadData != threadData) {qWarning("QCoreApplication: Application event filter cannot be in a different thread.");continue;}//调用过滤器的eventFilter函数进行过滤处理,如果返回true直接退出,不需要继续处理if (obj->eventFilter(receiver, event))return true;}}return false;
}//调用接收者的事件过滤器进行过滤
bool QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *receiver, QEvent *event)
{if (receiver != QCoreApplication::instance() && receiver->d_func()->extraData) {//遍历接收者的事件过滤器函数,进行过滤for (int i = 0; i < receiver->d_func()->extraData->eventFilters.size(); ++i) {QObject *obj = receiver->d_func()->extraData->eventFilters.at(i);if (!obj)continue;//过滤器和接收者不在同一线程,直接continueif (obj->d_func()->threadData != receiver->d_func()->threadData) {qWarning("QCoreApplication: Object event filter cannot be in a different thread.");continue;}//调用过滤函数进行过滤if (obj->eventFilter(receiver, event))//返回true将过滤事件return true;}}return false;
}

使用样例:

myobject.h
class myobject : public QObject
{Q_OBJECT
public:myobject(const QString &name, QObject *parent = nullptr):QObject(parent){m_name = name;}virtual ~myobject(){};
private:QString m_name;
protected:virtual void childEvent(QChildEvent *event);virtual bool eventFilter(QObject *watched, QEvent *event);
};myobject.cpp
void myobject::childEvent(QChildEvent *event)
{qDebug()<<"QChildEvent="<<event->type()<<objectName();
}bool myobject::eventFilter(QObject *watched, QEvent *event)
{qDebug()<<"eventFilter is"<<objectName()<<",event recver is"<<watched->objectName()<<",event is "<<event->type();//return false; //测试返回false时不过滤事件return true;//测试返回true时过滤事件
}main.cpp
int main(int argc, char *argv[])
{QApplication a(argc, argv);myobject *obj1= new  myobject("boj1");obj1->setObjectName("obj1");myobject *obj2= new  myobject("obj2");obj2->setObjectName("obj2");obj1->installEventFilter(obj2);//obj1事件会先走obj2的eventFilter函数,所以说这个eventFilter函数就不是给自己用的obj2->setParent(obj1);//触发obj1的QEvent::ChildAddedreturn a.exec();
}myobject::eventFilter返回true时,运行输出:
eventFilter is "obj2" ,event recver is "obj1" ,event is  QEvent::ChildAdded     myobject::eventFilter返回false时,运行输出:
eventFilter is "obj2" ,event recver is "obj1" ,event is  QEvent::ChildAdded
QChildEvent= QEvent::ChildAdded "obj1

void QObject::removeEventFilter(QObject *obj)

删除此对象事件筛选器对象obj。
当此对象被销毁时,此对象的所有事件过滤器将自动删除。
删除事件过滤器总是安全的,即使在事件过滤器激活期间(即从eventFilter()函数)。

void QObject::removeEventFilter(QObject *obj)
{Q_D(QObject);if (d->extraData) {for (int i = 0; i < d->extraData->eventFilters.count(); ++i) {if (d->extraData->eventFilters.at(i) == obj)d->extraData->eventFilters[i] = nullptr;}}
}

childEvent

childEvent有下面三种:
QEvent::ChildAdded, setParent或构造时传入parent时会触发parent的此事件
QEvent::ChildRemoved,setParent会从老父对象移除,老父对象触发此事件
QEvent::ChildPolished,当对象改变时触发此事件,
如QWidget的adjustSize(),setVisible(bool visible),showNormal,showMaximized,showFullScreen,showMinimized等

QObject默认空实现
void QObject::childEvent(QChildEvent * /* event */)
{
}void myobject::childEvent(QChildEvent *event)
{qDebug()<<"QChildEvent="<<event->type()<<objectName();
}myobject *obj1= new  myobject("obj1");
myobject *obj2= new  myobject("obj2");
myobject *obj3= new  myobject("obj3");
obj1->setObjectName("obj1");
obj1->setObjectName("obj2");
obj3->setObjectName("obj3");
obj3->setParent(obj1);//触发obj1的ChildAdded
obj3->setParent(obj2);//触发obj1的ChildRemoved和obj2的ChildAdded输出:
QChildEvent= QEvent::ChildAdded "obj1"
QChildEvent= QEvent::ChildRemoved "obj1"
QChildEvent= QEvent::ChildAdded "obj2"

customEvent

自定义事件的id范围:
QEvent::User = 1000, // 自定义事件的起始id
QEvent::MaxUser = 65535 // 自定义事件的最大id

一般都是继承后重写实现自己的功能
自定义事件3步骤:
1、注册事件类型调用int QEvent::registerEventType(int hint = -1 )
//一般我们不需要传hint。除非你要定义事件号值并根据值做一些判断,hint取值范围[1000,65535],
但是也有可能被别人注册过所以返回的不一定是传入的值,可以直接使用注册返回的值作为类型判断即可
2、继承QEvent实现自定义事件类 ,如果事件不带数据的话可以直接使用QEvent
3、实现customEvent事件
4、发送事件并自动调用customEvent函数

QObject默认空实现
void QObject::customEvent(QEvent * /* event */)
{
}//1定义两个事件类型
QEvent::Type myQEventType1 = static_cast<QEvent::Type>(QEvent::registerEventType());
QEvent::Type myQEventType2 = static_cast<QEvent::Type>(QEvent::registerEventType(1234));
//2继承QEvent
class myQEvent:public QEvent
{
public:myQEvent(Type type, const QString &data): QEvent(type), m_data(data){}QString m_data;//自定义事件传输的数据
};
//3实现customEvent事件
void myobject::customEvent(QEvent *event)
{qDebug()<<"customEvent="<<event->type()<<static_cast<myQEvent*>(event)->m_data;
}myobject *obj1= new  myobject("boj1");myobject *obj3= new  myobject("boj3");
//4发送事件并自动调用customEvent函数QApplication::sendEvent(obj1,new myQEvent(myQEventType1,"eeeeeeee"));QApplication::sendEvent(obj3,new myQEvent(myQEventType2,"wwwwwwwww"));//QApplication::sendEvent(obj3,new QEvent(myQEventType2));//如果不传递数据的话,直接new QEvent传入自定义事件类型即可
customEvent输出:ccustomEvent= QEvent::MaxUser "eeeeeeee"customEvent= QEvent::Type(1234) "wwwwwwwww"

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

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

相关文章

如何在 Edge 浏览器中设置自动刷新?

学习目标&#xff1a; 确定学习主题&#xff1a;明确你希望学习的主题或领域。这可以是一个具体的技能、学科或兴趣领域。 制定学习目标&#xff1a;确定你希望在学习过程中实现的具体目标。目标应该是明确、可测量和可实现的。 划分学习内容&#xff1a;将学习主题分解为更小…

从零学Java 集合概述

Java 集合概述 文章目录 Java 集合概述1 什么是集合?2 Collection体系集合2.1 Collection父接口2.1.1 常用方法2.1.2 Iterator 接口 1 什么是集合? 概念&#xff1a;对象的容器&#xff0c;定义了对多个对象进行操作的常用方法&#xff1b;可实现数组的功能。 和数组区别&…

Logo设计神器:适合新手的简易操作软件,快速入门!

标志设计软件在品牌营销和企业识别中发挥着重要作用。本文将对10款知名标志设计软件进行横向评价&#xff0c;从不同维度评价其功能、易用性、创意和适用性&#xff0c;帮助您选择最适合您需求的标志设计软件。 1.即时设计 推荐指数&#xff1a;★★★★★ 即时设计是一款功…

springboot 2.7 oauth server配置源码走读一

springboot 2.7 oauth server配置源码走读 入口&#xff1a; 上述截图中的方法签名和OAuth2AuthorizationServerConfiguration类中的一个方法一样&#xff0c;只不过我们自己的配置类优先级比spring中的配置类低&#xff0c;算是配置覆盖&#xff0c;看下图所示&#xff1a; …

某邦通信股份有限公司IP网络对讲广播系统挖矿检测脚本

目录 1.漏洞概述 2.影响版本 3.危害等级 4.挖矿程序检测 5.Nuclei自动化检测

阿里云国际服务器设置安全防护程序

阿里云云服务器&#xff08;ECS&#xff09;提供弹性、安全、高性能、高性价比的虚拟云服务器&#xff0c;满足您的所有需求。立即在这里免费注册&#xff01; 常见 Web 应用程序 请勿对 Web 服务控制台&#xff08;如 WDCP、TOMCAT、Apache、Nginx、Jekins、PHPMyAdmin、Web…

JavaScript数组sort()对负数排序的陷阱

前言 想着好久没去力扣刷题了&#xff0c;刚好手上的需求也差不多了&#xff0c;就去看了看。看到一个难度级别为困难的题&#xff0c;看到这个题想着直接使用JS现成的方法&#xff0c;先concat再sort。再取中间值不就实现了吗。是不是你们也这么想&#xff0c;哈哈哈。 就是…

11 个 Python全栈开发工具集

前言 以下是专注于全栈开发不同方面的 Python 库;有些专注于 Web 应用程序开发&#xff0c;有些专注于后端&#xff0c;而另一些则两者兼而有之。 1. Taipy Taipy 是一个开源的 Python 库&#xff0c;用于构建生产就绪的应用程序前端和后端。 它旨在加快应用程序开发&#xf…

2024--Django平台开发-Django知识点(五)

day05 django知识点 今日概要&#xff1a; 中间件 【使用】【源码】cookie 【使用】【源码 - Django底层请求本质】session【使用】【源码 - 数据库请求周期中间件】 1.中间件 1.1 使用 编写类&#xff0c;在类型定义&#xff1a;process_request、process_view、process_…

优化改进YOLOv5算法之Dilation-wise Residual(DWR)可扩张残差注意力模块,增强多尺度感受野特征,助力小目标检测

目录 1 Dilation-wise Residual模块原理 1.1 设计动机 1.2 Dilation-wise Residual模块 1.2.1 Design idea and structure 1.2.2 Parameter design

【C++】STL 算法 ⑨ ( 预定义函数对象示例 - 将容器元素从大到小排序 | sort 排序算法 | greater<T> 预定义函数对象 )

文章目录 一、预定义函数对象示例 - 将容器元素从大到小排序1、sort 排序算法2、greater<T> 预定义函数对象 二、代码示例 - 预定义函数对象1、代码示例2、执行结果 一、预定义函数对象示例 - 将容器元素从大到小排序 1、sort 排序算法 C 标准模板库 ( STL , Standard Te…

离散数学-二元关系

4.1关系的概念 1)序偶及n元有序组 由两个个体x和y&#xff0c;按照一定顺序排序成的、有序数组称为有序偶或有序对、二元有序组&#xff0c; 记作<x&#xff0c;y>&#xff0c;其中x是第一分量&#xff0c;y是第二分量。 相等有序偶&#xff1a;第一分量和第二分量分…

游戏开发中,你的游戏图片压缩格式使用ASTC了吗

文章目录 ASTC原理&#xff1a;使用要求 ASTC&#xff08;Adaptive Scalable Texture Compression&#xff0c;自适应可伸缩纹理压缩&#xff09;是一种高级的纹理压缩技术&#xff0c;由ARM公司开发并推广。它在图形处理领域中因其出色的压缩效率和灵活性而受到广泛关注。 AST…

前端国际化之痛点(二):多包多库场景下联动多语言

前言 VoerkaI18n是一款非常优秀的前端国际化解决方案&#xff0c;其开发的出发点是为了解决现存多语言的一些痛点,接下来几篇文章将分别进行分析。 前端国际化之痛点(一)&#xff1a;让人头疼的词条Key前端国际化之痛点(二)&#xff1a;多包多库场景下联动多语言前端国际化之…

Jetson Orin AGX 64GB更新 Jetpack6.0

Jetson Orin AGX 64GB更新 Jetpack6.0 注意&#xff1a; 1&#xff0c;如果你要向我一样为AGX更新Jetpack6.0的话&#xff0c;它还要求你的ubuntu版本必须是20.04 或22.04 2&#xff0c;安装完SDKmanager后&#xff0c;然后选择对应的设备&#xff0c;根据个人选择勾选是否安装…

【Mysql】InnoDB 引擎中的页目录

一、页目录和槽 现在知道记录在页中按照主键大小顺序串成了单链表。 那么我使用主键查询的时候&#xff0c;最顺其自然的办法肯定是从第一条记录&#xff0c;也就是 Infrimum 记录开始&#xff0c;一直向后找&#xff0c;只要存在总会找到。这种在数据量少的时候还好说&#x…

四、K8S-Deployment(无状态服务)

目录 一、引入Deployment 二、Deployment资源清单 三、Deployment支持的功能 1、扩缩容 1、通过命令行方式修改 2 、在线编辑yaml文件方式修改 2、镜像更新 1、重建更新 2、滚动更新 3、金丝雀发布&#xff08;灰度更新&#xff09; [rootk8s-master-1 ~]# kubectl g…

【笔记】Helm-2 如何使用-2 同步你的仓库

同步你的仓库 注意&#xff1a;该示例是专门针对Google Cloud Storage&#xff08;GCS&#xff09;提供的chart仓库。 先决条件 安装gsutil工具。我们非常依赖gsutil rsync功能 https://cloud.google.com/storage/docs/gsutil 确保可以使用Helm程序 可选&#xff1a;我们推…

centos用yum安装mysql详细教程

1 查询安装mysql的yum源,命令如下 ls /etc/yum.repos.d/ -l 界面如下图所示&#xff0c;未显示mysql的安装源 2 安装mysql相关的yum源,例如&#xff1a; 例如&#xff1a;rpm -ivh mysql57-community-release-el7.rpm 要注意 mysql的版本和系统的版本匹配 mysql57-communi…

【高等数学之泰勒公式】

一、从零开始 1.1、泰勒中值定理1 什么是泰勒公式?我们先看看权威解读: 那么我们从古至今到底是如何创造出泰勒公式的呢? 由上图可知&#xff0c;任一无穷小数均可以表示成用一系列数字的求和而得出的结果&#xff0c;我们称之为“无穷算法”。 那么同理我们想对任一曲线来…