Qt 学习之路 2(23):自定义事件

2023-10-27

尽管 Qt 已经提供了很多事件,但对于更加千变万化的需求来说,有限的事件都是不够的。例如,我要支持一种新的设备,这个设备提供一种崭新的交互方式,那么,这种事件如何处理呢?所以,允许创建自己的事件 类型也就势在必行。即便是不说那种非常极端的例子,在多线程的程序中,自定义事件也是尤其有用。当然,事件也并不是局限在多线程中,它可以用在单线程的程序中,作为一种对象间通讯的机制。那么,为什么我需要使用事件,而不是信号槽呢?主要原因是,事件的分发既可以是同步的,又可以是异步的,而函数的调用或者说是槽的回调总是同步的。事件的另外一个好处是,它可以使用过滤器。

Qt 自定义事件很简单,同其它类库的使用很相似,都是要继承一个类进行扩展。在 Qt 中,你需要继承的类是QEvent

继承QEvent类,最重要的是提供一个QEvent::Type类型的参数,作为自定义事件的类型值。回忆一下,这个 type 是我们在处理事件时用于识别事件类型的代号。比如在event()函数中,我们使用QEvent::type()获得这个事件类型,然后与我们定义的实际类型对比。

QEvent::TypeQEvent定义的一个枚举。因此,我们可以传递一个 int 值。但是需要注意的是,我们的自定义事件类型不能和已经存在的 type 值重复,否则会有不可预料的错误发生。因为系统会将你新增加的事件当做系统事件进行派发和调用。在 Qt 中,系统保留 0 – 999 的值,也就是说,你的事件 type 要大于 999。这种数值当然非常难记,所以 Qt 定义了两个边界值:QEvent::UserQEvent::MaxUser。我们的自定义事件的 type 应该在这两个值的范围之间。其中,QEvent::User的值是 1000,QEvent::MaxUser的值是 65535。从这里知道,我们最多可以定义 64536 个事件。通过这两个枚举值,我们可以保证我们自己的事件类型不会覆盖系统定义的事件类型。但是,这样并不能保证自定义事件相互之间不会被覆盖。为了解决这个问题,Qt 提供了一个函数:registerEventType(),用于自定义事件的注册。该函数签名如下:

1
static int QEvent :: registerEventType ( int hint = - 1 ) ;

这个函数是 static 的,因此可以使用QEvent类直接调用。函数接受一个 int 值,其默认值是 -1;函数返回值是向系统注册的新的 Type 类型的值。如果 hint 是合法的,也就是说这个 hint 不会发生任何覆盖(系统的以及其它自定义事件的),则会直接返回这个值;否则,系统会自动分配一个合法值并返回。因此,使用这个函数即可完成 type 值的指定。这个函数是线程安全的,不必另外添加同步。

我们可以在QEvent子类中添加自己的事件所需要的数据,然后进行事件的发送。Qt 中提供了两种事件发送方式:

  1. 1
    2
    static bool QCoreApplication :: sendEvent ( QObject * receiver ,
                                             QEvent * event ) ;

    直接将event事件发送给receiver接受者,使用的是QCoreApplication::notify()函数。函数返回值就是事件处理函数的返回值。在事件被发送的时候,event对象并不会被销毁。通常我们会在栈上创建event对象,例如:
    1
    2
    QMouseEvent event ( QEvent :: MouseButtonPress , pos , 0 , 0 , 0 ) ;
    QApplication :: sendEvent ( mainWindow , & event ) ;
  2. 1
    2
    static void QCoreApplication :: postEvent ( QObject * receiver ,
                                             QEvent * event ) ;

    event事件及其接受者receiver一同追加到事件队列中,函数立即返回。

    因为 post 事件队列会持有事件对象,并且在其 post 的时候将其 delete 掉,因此,我们必须在堆上创建event对象。当对象被发送之后,再试图访问event对象就会出现问题(因为 post 之后,event对象就会被 delete)。

    当控制权返回到主线程循环是,保存在事件队列中的所有事件都通过notify()函数发送出去。

    事件会根据 post 的顺序进行处理。如果你想要改变事件的处理顺序,可以考虑为其指定一个优先级。默认的优先级是Qt::NormalEventPriority

    这个函数是线程安全的。

    Qt 还提供了一个函数:

    1
    2
    static void QCoreApplication :: sendPostedEvents ( QObject * receiver ,
                                                   int event_type ) ;

    这个函数的作用是,将事件队列中的接受者为receiver,事件类似为 event_type 的所有事件立即发送给 receiver 进行处理。需要注意的是,来自窗口系统的事件并不由这个函数进行处理,而是processEvent()。详细信息请参考 Qt API 手册。

现在,我们已经能够自定义事件对象,已经能够将事件发送出去,还剩下最后一步:处理自定义事件。处理自定义事件,同前面我们讲解的那些处理方法没有什么区别。我们可以重写QObject::customEvent()函数,该函数接收一个QEvent对象作为参数:

1
void QObject :: customEvent ( QEvent * event ) ;

我们可以通过转换 event 对象类型来判断不同的事件:

1
2
3
4
void CustomWidget :: customEvent ( QEvent * event ) {
     CustomEvent * customEvent = static_cast < CustomEvent * > ( event ) ;
     // ...
}

当然,我们也可以在event()函数中直接处理:

1
2
3
4
5
6
7
8
bool CustomWidget :: event ( QEvent * event ) {
     if ( event -> type ( ) == MyCustomEventType ) {
         CustomEvent * myEvent = static_cast < CustomEvent * > ( event ) ;
         // processing...
         return true ;
     }
     return QWidget :: event ( event ) ;
}




FROM:  http://www.devbean.net/2012/10/qt-study-road-2-custom-event/


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

Qt 学习之路 2(23):自定义事件 的相关文章

  • Azure微软云

    什么是 Azure 虚拟网络 Azure 虚拟网络 VNet 是 Azure 中专用网络的基本构建块 VNet 使多种类型的 Azure 资源 例如 Azure 虚拟机 VM 能够安全地相互通信 Internet 和本地网络 VNet 类似
  • 【工具】自动搜索Research网站的学术会议排名

    转载请注明出处 小锋学长生活大爆炸 xfxuezhang cn Research com是一个可以搜索学术会议网站的影响因子的网站 好用是好用 但有一个缺点 得手动选择类目 有这么多类目 一个个手动选也太累了 所以做了一个自动搜索的小工具
  • 区块链的技术挑战

    2016年年初 中国人民银行举行数字货币研讨会之后 区块链的概念作为数字货币的关键技术进入了公众视 野 也正是进入2016年后 区块链成为年度各大领域讨论的关键性话题 因为 虽然很多人对区块链并不是十分了解 但是该技术对于金融业 医疗行业
  • 使用keil5仿真和逻辑仪分别观察引脚电平变化

    文章目录 用keil5仿真观察 使用SaleaeLogic16进行协议分析 总结心得 参考资料 用keil5仿真观察 打开 l上一篇 完成的keil工程 直接打开仿真示波器运行时会自动停止 并报错某些地址没有写的权限 此时需要在工程下添加一
  • 数据结构----线性表顺序存储的基本操作

    线性表的抽象数据类型定义 ADT LinearList 数据元素 D ai ai D i 1 2 3 n n gt 0 D 为某一数据类型 结构关系 R lt ai a i 1 gt ai a i 1 D i 1 2 3 n 1 基本操作
  • 华为od机试 C++ 【url拼接】

    题目 题目 给定一个URL的前缀和后缀 我们需要将其合并成一个完整的URL 在合并时 请注意以下几点 如果前缀的结尾没有斜线 而后缀的开头也没有斜线 那么在两者之间需要添加一个斜线 如果前缀的结尾和后缀的开头都有斜线 那么需要保留其中的一个
  • uni.app的剪切板

    uni setClipboardData data this title success function res console log success
  • 微信哪个电话能转人工服务器,如何联系微信人工客服?掌握好窍门,只需30秒可接通,亲测有效...

    原标题 如何联系微信人工客服 掌握好窍门 只需30秒可接通 亲测有效 很多人都会使用微信 但是使用过程中难免会遇到问题 比如账号封号 转错账 支付问题等 如果在机器人自动回答中解决不了问题 想找人工客服就是难上加难 有人说微信人工客服是微信
  • 毕业设计-基于卷积神经网络的指针式仪表识别系统

    目录 前言 课题背景和意义 实现技术思路 一 仪表的识别系统 二 实验及结果分析 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为毕业后面临的就业升学做准备 一边要为毕业设计耗费大量精力 近几年各个学校要求
  • vue3+element-plus el-form表单组件二次封装(vue3+ts项目)TForm组件新增继承 Element-plus 组件的事件使用及el-input 去除前后空格

    2023 03 06 TForm组件新增继承 Element plus 组件的事件使用及el input 去除前后空格 type password 除外 一 简介 HTML 一行代码 可实现表单输入框 日期选择 下拉选择 复选框选中等及规则

随机推荐

  • Spark安装的三种方式

    Spark安装的三种方式 通用配置 部署local模式 直接解压即可 不需要配置 部署Standalone模式 部署Yarn模式 通用配置 解压 tar zxf usr local intsall spark 3 1 1 bin hadoo
  • Java中的private关键字

    private关键字用于类中 作用是保护类中的成员变量或者成员方法的数据安全 凡是被private修饰过后的成员变量或成员方法都不能直接被外界调用 需要先在类中进行数值的修饰才可以被外界调用 private的使用 private 数据类型
  • 名词的过去式

    名词作谓语时 可以有过去式 名词 否定形式 名词 例如 昨日 雨 昨天下雨了 昨日 雨 昨天没下雨
  • 【Struct(结构体)杂谈之六】无既是有---没有成员变量的Struct(结构体)

    没有成员变量的Struct 结构体 在开始本篇之前 想问大家一个问题 0是什么 呵呵 就是没有呗 那好 这5块钱拿去 就当抵我上次向你借的500块钱 什么 这哪和哪啊 这不一样 可是你自己说的 0就是 没有 我说不清 反正不行 你必须还我5
  • PAT的配置

    PAT工作原理 端口映射NAPT指除了使用IP之外 还使用端口号来建立映射 NAPT是实现多个内网主机共享一个公网IP接入的关键技术 NAPT建立映射需要用到传输层的TCP和UDP的端口号 在网络数据传输中 大部分是通过端到端的连接来进行数
  • e480 黑苹果_GitHub - aliyoge/Hackintosh-ThinkPad-E480: Thinkpad E480 for macOS Catalina

    Thinkpad E480 for macOS Catalina Hackintosh your Thinkpad E480 让你的Thinkpad E480装上黑苹果 电脑配置 规格 详细信息 电脑型号 联想ThinkPad 翼480 0
  • ds18b20温度转换指令_DS18B20温度传感器(附代码并浅谈与或运算)

    DS18B20使用的是一种比较特殊的传输协议 仅需一个接线口就能实现通信 前言 DS18B20独特的单线接口仅需一个端口引脚进行通讯 这让每一个学习到这里的人都感到很神奇 在这篇文章中我们将通过学习18B20的数据传输方式来为IIC协议做下
  • 2022正式结束全年总基调,向2023迈向新征程

    不可言说的另一个自己 毕业已经五个月有余 先来汇报一下总体情况 总共自主独立完成两个项目 毕业后分别学习了部分spark docker 达梦数据库 Oracle数据库操作及命令 并且这些大部分都有过实际操作 当然 最主要的还是我主要使用的P
  • VerilogHDL概述与数字IC设计流程学习笔记

    VerilogHDL概述与数字IC设计流程学习笔记 一 HDL的概念和特征 HDL Hard Discrimination Language的缩写 翻译过来就是硬件描述语言 那么什么是硬件描述语言呢 为什么不叫硬件设计语言呢 硬件描述语言
  • Linux 修改SSH端口

    如果防火墙 或防火墙已经开启 需要先开放2222端口 firewall cmd add port 2222 tcp permanent zone public firewall cmd reload 编辑文件 vim etc ssh ssh
  • ajax中GET和POST区别

    ajax中GET和POST区别 get和post的区别 1 语义化的区别 get偏向于获取 post偏向于提交数据 2 携带给后端的信息位置不一样 get直接在地址后面拼接查询字符串 post在请求体内进行信息的查询 3 携带的数据格式不一
  • CTF Web入门题目——Bugku Web 题目题解——发送HTTP请求篇(3道基础题目)

    1 Bugku web基础 GET http 123 206 87 240 8002 get 题目 思路 关键是分析PHP代码 what get what 意思是用get方式提交what的值 if what flag echo flag 要
  • Postman脚本——解析响应体和获取请求参数

    解析响应体 为了在响应中执行断言 首先需要将数据解析为断言可以使用的JavaScript对象 解析JSON const responseJson pm response json 解析xml const responseXml xml2Js
  • 30多岁转行医疗器械维修行业有前景吗

    年也过完了 大家也都回归岗位了 以全新状貌去迎接新的一年 选择一个对的行业将造就大批量的富翁 最近很多人也踏上了找工作的道路 大环境后不确定未来还有什么等着我们 每每晚上就会失眠 何去何从 到底该怎么办 思虑过后很多人发现大环境下医疗行业好
  • (附源码)Springboot宠物领养系统 毕业设计 241104

    Springboot宠物领养系统 摘 要 如今 随着人们生活水平不断提高 人们的生活在物质满足的基础上 更多的人将生活的重点放在追求精神享受的过程中 于此同时 Internet铺天盖地的普及 使得这样的人纷纷通过Internet的方式去寻找
  • 单缓冲区和双缓冲区

    单缓冲区 在单缓冲情况下 每当用户进程发出一I O请求时 OS便在主存中为之分配一缓冲区 在块设备输入时 假定从磁盘把一块数据输入到缓冲区的时间为T OS将该缓冲区中的数据传送到用户区的时间为M 而CPU对这一块数据的处理时间为C T和C是
  • 【STM32】PWM输出原理

    目录 PWM模式的工作框架 PWM模式的工作原理 PWM库函数配置 1 初始化定时器输出通道 TIM OC2Init 2 设置比较值函数 TIM SetComparex 3 使能预装载寄存器 void TIM OC2PreloadConfi
  • Ubuntu18.04添加右键菜单

    本文以添加右键使用vscode打开为例 1 进入 local share nautilus scripts文件夹 cd local share nautilus scripts 2 创建文件 vim Vscode it 3 添加相应脚本 b
  • python报错:argument 1 must be pygame.surface.Surface, not builtin_function_or_method解决方法

    1 报错分析 根据报错信息 提示我们出错的原因在与第一个参数类型必须是pygame类型 但是我们的参数类型不匹配 2 源码分析 这里的方法blit 中的第一个参数是STATICSURF 一个全局常量 根据报错我们知道是它出了问题 我们找到这
  • Qt 学习之路 2(23):自定义事件

    尽管 Qt 已经提供了很多事件 但对于更加千变万化的需求来说 有限的事件都是不够的 例如 我要支持一种新的设备 这个设备提供一种崭新的交互方式 那么 这种事件如何处理呢 所以 允许创建自己的事件 类型也就势在必行 即便是不说那种非常极端的例