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

Qt:事件

目录

处理事件

鼠标事件

键盘事件

定时器事件

窗口事件


虽然 Qt 是跨平台的 C++ 开发框架,Qt 的很多能力其实是操作系统提供的
只不过 Qt 封装了系统的 API

事件

前面学习过信号槽:
用户进行的各种操作,就可能会产生出信号,可以给某个信号指定槽函数,当信号触发时,就能够自动的执行到对应的槽函数

事件和信号槽非常类似:
用户进行的各种操作,也会产生事件,程序员同样可以给事件关联上处理函数(处理的逻辑),当事件触发的时候,就能够执行到对应的代码

事件本身是操作系统提供的机制,Qt 也同样把操作系统事件机制进行了封装,拿到了 Qt 中
但是由于事件对应的代码编写起来不是很方便,所以 Qt 对于事件机制又进行了进一步的封装,就得到了信号槽

信号槽就是对于事件的进一步封装,事件是信号槽的底层机制

实际 Qt 开发程序过程中,绝大部分和用户之间进行的交互都是通过"信号槽"来完成的
有些特殊情况下,信号槽不一定能搞定(某个用户的动作行为,Qt 没有提供对应的信号)
此时就需要通过重写事件处理函数的形式,来手动处理事件的啊应逻辑

开发事件机制给咱们程序员,咱们就可以根据实际的需要进行更深度的定制化 diy 操作了

用户进行了很多操作,就会产生很多的事件(当然也会产生很多的信号)

下面就是开发中比较典型的事件:

不同场景下,要关注的点是不一样,这些事件的子类中就会包含一些对应的不同的属性


处理事件

让一段代码和某个事件关联起来,当事件触发的时候,就能指定到这段代码
之前信号槽这里通过 connect 来完成上述关联的

对于事件来说,还不太一样:
让当前的类,重写某个事件处理函数,这里用到的是"多态”机制
创建子类, 继承自 Qt 已有的类,在子类中重写父类的事件处理函数
后续事件触发过程中,就会通过多态这样的机制,执行到咱们自己写的子类的函数中

鼠标事件

下面都是创建 QWidget 的,当然也可以创建 QMainWindow,因为用不到工具栏,所以选择的 QWidget

鼠标进入和鼠标离开事件

下面使用上述方式,处理一下鼠标进入(enterEvent)和鼠标离开(leaveEvent)事件:
enterEvent 和 leaveEvent 函数都是虚函数,所以可以被子类重写:

图形化界面的方式创建一个 Label,鼠标进入 Label 时提示 enterEvent,离开时提示 leaveEvent:
为了能清楚看到 Label 的边框,将边框选为 Box

 效果为:

这里需要创建 QLabel 的子类,重写 enterEvent 和 leaveEvent:

类名就叫 Label,父类叫 QLabel:

按照以往的习惯,创建的 Label 类需要有一个父控件,所以在 label.h 中添加:

label.cpp 中添加:


接着在 label.h 中声明两个需要重写的函数:

注意:
要想重写父类的函数,就需要确保你这边写的函数名字和函数的参数列表都完全一致 (形参名无所谓),谨防单词拼写错误

label.cpp 实现:

(void)event 是为了消除警告,因为暂时还没用到 event 这个形参

此时运行程序,鼠标进入和移出 label 时并没有执行上述逻辑,因为:
当前在界面上创建的这个 label 其实是 QLabel,不是咱们自己写的 Label
必须要确保界面上的这个 label 是一个咱们自己定义的 Label 类的实例,才会执行到

右键图形化界面的 label,点击提升为:

输入提升的类名 Label,点击添加,再点击提升:
一定要确保你的类名以及头文件的名字,和上述自定义的类名头文件都匹配

此时右边对象树上面就是 Label 了,没提升前显示是 QLabel:

通过"提升为"这样的方式,就可以把 Qt Designer 中拖上去的控件的类型转换成自定义的控件类型

此时再运行程序,鼠标移入移出 Label 时,就会打印下面的内容了:

此时就说明当前的 enterEvent 和 leaveEvent 这两个事件就被咱们给捕获到了


通过事件获取到鼠标点击的位置

与上面的操作一样,创建一个 Label,再创建一个 Label 类,父类定为 QLabel,并对生成的 Label 的构造函数做一个调整,添加一个 QWidget* 的参数,以便于能够指定父窗口
接着再右键 Label 点击提升为,输入类名后点击提升,此时就完成了提升操作:

下面就是 mousePressEvent 函数,当鼠标按下时就会触发这个函数调用:
左键、右键、滚轮、侧键都能触发

在 label.cpp 中实现 mousePressEvent 函数:

此时鼠标在 Label 范围内点击就会打印 鼠标点击的位置坐标:
上述是以 Label 左上角位置为原点的

下面则是以屏幕左上角为原点获取坐标:

也可以加上下面的代码,来判断按下的是左键还是右键:


通过事件获取到鼠标点击释放按键

与上面的鼠标点击事件一样,下面是重写的 mouseReleaseEvent 函数:

此时就能做到获取鼠标点击释放按键:

clicked 这样的信号,就相当于是一次鼠标按下事件和一次鼠标释放事件


通过事件获取到鼠标双击按键

重写的 mouseDoubleEvent 函数如下:

鼠标第二次按下的时候,才能够识别到是"双击:

注意:
有的程序,可能是单击有一些逻辑,双击有另一些逻辑,如果我们没注意,可能双击操作就能触发单击的逻辑,可能就有 bug


通过事件获取到鼠标移动

刚才重写鼠标事件的操作,都是在自定义的 Labe| 中完成的,此时鼠标只有在 Label 范围内进行动作的时候,才能捕获到
也可以把这些操作直接放到 Widget (QWidqet 子类) 来完成,这样的话,鼠标在整个窗口中进行的各种动作都能获取到了

所以直接在 widget.h widget.cpp 中重写 mouseMoveEvent 函数:

此时运行程序并没有效果

鼠标移动不同于鼠标按下
随便移动一下鼠标,就会产生出大量的鼠标移动事件,当你进行捕获事件的时候,尤其是在这里再进行一些复杂逻辑的时候,程序负担就很重,很容易产生卡顿之类的情况
Qt 为了保证程序的流畅性,默认情况下不会对鼠标移动进行追踪,鼠标移动的时候不会调用mouseMoveEvent,除非显式告诉 Qt 就要追踪鼠标位置

所以需要在 Widget 的构造函数中设置:

此时稍微一动鼠标,就会一直打印,如果移动的比较快,就会明显出现打印卡顿的情况:


通过事件获取到鼠标滚轮的滚动动作

在 QWheelEvent 中 通过 delta() 获取到这次事件鼠标滚轮滚动了多远

同样在 widget.h widget.cpp 中重写 wheelEvent 函数:

滚轮往下滚动就打印 -120,往上滚动就打印 120:

我们也可以在 Widget 类中新增 int total,初始化为0,就能在 wheelEvent 函数中实现统计滚轮滚动的距离了:

效果为:

就可以根据滚轮滚动的操作实现特定的功能,比如可以通过滚轮去缩放字体大小,可以把滚轮滚动的距离映射到具体的数值上,就可以实现类似的效果了


键盘事件

处理键盘按键事件

我们前面学习过的 QShortCut,这是信号槽机制封装过的,获取键盘按键的方式

站在更底层的角度,也可以通过事件获取到当前用户键盘按下的情况

依旧是在 widget.h widget.cpp 中重写 keyPressEvent 函数:

按下 ABCDEF 的效果为,可以发现每一个按钮都对应一个数字:

如果想得知是否按下了具体的某一个键,以 A 为例,代码改为:

也有些场景是组合键 Ctrl + A :


定时器事件

前面学习了QTimer 实现定时器功能
在 QTimer 背后是 QTimerEvent 定时器事件进行支撑的

QObject 提供了一个 timerEvent 这个函数,可以通过定时器,周期性的触发一些操作
里面需要搭配 startTimer 启动定时器,killTimer 关闭定时器 使用

下面通过图形化的方式,拖动一个 LCD Number,初始值改为 10 :

此处 startTimer 的返回值 timerld 类似于 Linux 中的文件描述符,起到的是身份标识的效果

因为后面程序可能还会用到 timerld,所以在 widget.h 中的构造函数定义为类内成员:

在 widget.h widget.cpp 中重写 timerEvent 函数:

运行程序,每隔一秒-1,直到0就停止:

使用 timerEvent 比 QTimer 还是要更复杂一点,手动管理 timerld,还需要区分这次函数调用是哪个 timer 引起的
后续实际开发中,使用 QTimer 即可


窗口事件

  • moveEvent 窗口移动时触发的事件
  • resizeEvent 窗口大小改变时触发的事件

 moveEvent

QMoveEvent 中有下面两个常用的方法:

resizeEvent

QResizeEvent 中有下面两个常用的方法:


在 widget.h widget.cpp 中重写 moveEvent 和 resizeEvent函数:

如果移动 widget 窗口或调整 widget 窗口大小,下面就会打印:


Qt:事件相关知识到此结束

相关文章:

Qt:事件

目录 处理事件 鼠标事件 键盘事件 定时器事件 窗口事件 虽然 Qt 是跨平台的 C 开发框架,Qt 的很多能力其实是操作系统提供的 只不过 Qt 封装了系统的 API 事件 前面学习过信号槽: 用户进行的各种操作,就可能会产生出信号,可以…...

python 程序一次启动有两个进程的问题(flask)

0. 背景 写了一个使用 flask 作为服务框架的程序,发现每次启动程序的时候,使用 ps 都能观察到两个 python 进程。 此外,这个程序占用了 GPU 资源,我发现有两个 python 进程,分别占用了完全相同的 GPU 显存 1. 原因 …...

ethtool的资料

ethtoolethtool(8) — Linux manual pageethtool(8) - Linux man pageUsing ethtool in LinuxLooking at your Linux system’s network interface with ethtoolHow to Change Speed & Duplex of Ethernet Card in Linux with ethtool CommandNVIDIA EthtoolRed Hat Enterp…...

SpringBoot过滤器(Filter)的使用:Filter接口、FilterRegistrationBean类配置、@WebFilter注释

1、过滤器(Filter)的介绍 Spring Boot 的过滤器用于对数据进行过滤处理。通过 Spring Boot 的过滤器,程序开发人员不仅可以对用户通过 URL 地址发送的请求进行过滤处理(例如:过滤一些错误的请求或者请求中的敏感词等),而且可以对服务器返回的数据进行过滤处理(例如:压…...

“此电脑”中删除WPS云盘方法(百度网盘通用)

📣此方法适用于卸载WPS云盘后,WPS云盘图标依然在此电脑中显示的问题。 原理:通过注册来进行删除 步骤: WIN键R,打开运行窗口,输入regedit命令,来打开【注册表编辑器】; 从左侧,依…...

Manus AI:开启Agent元年的ChatGPT时刻(附赠资料)

1. Manus AI:全球首个通用Agent Manus AI 是全球首个通用人工智能代理,连接思想与行动,不仅思考,还能交付成果。Manus 擅长处理工作和生活中的各种任务,帮助用户完成一切。其核心理念是“less structure, more intell…...

ChromeDriver下载 最新版本 134.0.6998.35

平时为了下个驱动,到处找挺麻烦,收集了很多无偿分享给需要的人,仅供学习和交流。 ChromeDriver及浏览器134.0.6998.35 ChromeDriver及浏览器133.0.6943.141 ChromeDriver 102.0.5005.61 ChromeDriver 105.0.5195.102 ChromeDriver 108.0…...

Sass进阶之路:@forward 的可见性控制与变量覆盖

文章目录 前言1. 转发导入2. 添加前缀3. 控制可见性4. 转发时修改默认值总结 前言 在上一篇中,我们深入探讨了 use 的使用, 也介绍了 use 在使用深层模块中的变量时具有一定的缺点。所以在本文中,我们将深入解析 forward 的核心用法。 1. 转…...

MySQL作业一

一、创建数据库 #创建数据库 mysql> create database db_ck; Query OK, 1 row affected (0.01 sec)mysql> show databases like "db_%"; ----------------- | Database (db_%) | ----------------- | db_ck | | db_system | ----------------…...

虚拟机总结| 关于虚拟机的一些配置总结

前言 每次安装新的虚拟机都需要重新在网上搜索如何配置网络,我需要写一个自己的部署步骤,增加工作效率,不用每次配置的时候再去网上去翻找。 1.只需要联网功能记录(不固定IP) 1.1 修改ifcfg-ens33 vi etc/sysconfig/network-scripts/ifcfg…...

leetcode-sql数据库面试题冲刺(高频SQL五十题)

题目: 577.员工奖金 表:Employee -------------------- | Column Name | Type | -------------------- | empId | int | | name | varchar | | supervisor | int | | salary | int | -------------------- empId 是该表中具有唯一值的列。 该表的每一行…...

OpenManus:解锁测试工程师的效率密码——实践与应用指南

随着软件行业的快速发展,测试工程师面临的挑战也日益增多:如何在有限的时间内保证产品质量、如何高效生成测试数据、如何快速定位问题根源?这些问题直接影响到产品上线的节奏和用户体验。而在这一背景下,开源项目 OpenManus 的出现…...

Mybatis中的设计模式

1. 工厂模式(Factory Pattern) 概念:工厂模式是一种创建对象的设计模式,它将对象的创建和使用分离,通过一个工厂类来负责创建对象。MyBatis 中的应用:MyBatis 使用 SqlSessionFactory 来创建 SqlSession 对…...

[PWNME 2025] PWN 复现

这种比赛得0也不容易,前边暖声还是能作的。 GOT 指针前溢出,可以溢出到GOT表,然后把后门写上就行 Einstein 这个拿到WP也没复现成,最后自己改了一下。 int __cdecl handle() {int offset; // [rsp8h] [rbp-38h] BYREFunsigne…...

【笔记】记一次easyExcel中注解ExcelProperty映射字段赋值无效问题

背景 最近在开发一个导入excel文件解析数据并入库的功能,导入过程中出现一个BUG:后端映射实体字段pType没有被赋值,但是导入的excel源文件是有数据。 定位问题 经过debug源码发现最终创建对象并赋值使用的是net.sf.cglib.beans.BeanMap类中…...

肖恩的n次根

1.肖恩的n次根 - 蓝桥云课 问题描述 喜欢研究数学问题的肖恩注意到,在编程语言中通常内置函数只有开平方根和开立方根,但是肖思想知道开高次方根(大于3次方称为高次方),应该怎么做。请你设计一个程序来帮帮肖恩。 输…...

《AI浪潮下的创新枢纽:火山引擎大模型应用实验室平台》

《AI浪潮下的创新枢纽:火山引擎大模型应用实验室平台》 引言:AI 时代的新引擎 在科技飞速发展的当下,人工智能(AI)已不再是遥不可及的概念,它如同一股汹涌的浪潮,席卷了我们生活的每一个角落。…...

生成式AI系列(二) LLM生成质量改善的方法——RAG检索增强生成

一、引子 我们需要通过一些手段来提升LLM生成内容质量,主要的有下面三项,本文将主要介绍RAG。 1. 提示工程(Prompt Engineering) 通过精心设计的提示(Prompt)来提升输出的质量 2. 模型微调(Fi…...

Visual studio + Qt 项目配置管理

Visual studio Qt 项目配置管理 1.本机顺利安装 vs 和 Qt 软件 ​ 并且设置好Qt 的环境变量比如 E:\Qt\Qt5.9.8\5.9.8\msvc2017_64\bin E:\Qt\Qt5.9.8\5.9.8\msvc2017_64\lib E:\Qt\Qt5.9.8\5.9.8\msvc2017_64\include //这里是你电脑上Qt的路径,每台电脑不一样…...

直装永久授权,最新专业版集成VB7

无论是学生、教师还是职场工作人员,办公软件在日常工作和学习中都是不可或缺的重要工具。在众多办公软件中,微软的Microsoft Office和金山软件的WPS Office最常用的选择。对于许多使用要求不高的小伙伴而言,WPS Office因其易用性和免费版本的…...

AI数字人| Fay开源项目、UE5数字人、本地大模型

数字人实践教程 本教程主要是讲如何在本地UE部署Fay数字人的开源框架。 最终效果可以与人进行自然语言的对话,花了大概10个h的时间到,踩了很多坑,同样想实现的朋友可以作为参考 参考文档:Fay 数字人开源框架 - 飞书云文档 官方的教…...

【网络编程】同步和异步、阻塞和非阻塞,I/O和网络I/O

十、基于I/O模型的网络开发 10.1 同步和异步 对于多个线程而言,同步、异步就是线程间的步调是否要一致、是否要协调:要协调线程 之间的执行时机就是线程同步,否则就是异步。 对于一个线程的请求调用来讲,同步和异步的区别是是否…...

第本章:go 切片

注意: 切片必须要初始化 才能使用 ,切片是引用类型 a :[]int{} // 这上叫始化 此时并没有申请内存 // 如果要追加值的话: append ints : append(a, 1, 2, 3)a : make([]int,5) // 声明切片类型var a []string //声明一…...

VsCode导入时选择相对路径

自动导入时总是以db://开头了,而我们通常需要的是相对路径,对VsCode进行如下设置: 打开 VSCode 设置: 使用快捷键 Ctrl ,(Windows/Linux)或 Cmd ,(Mac)。 或者在菜单栏中选择 …...

CarPlanner:用于自动驾驶大规模强化学习的一致性自回归轨迹规划

25年2月来自浙大和菜鸟网络的论文“CarPlanner: Consistent Auto-regressive Trajectory Planning for Large-scale Reinforcement Learning in Autonomous Driving”。 轨迹规划对于自动驾驶至关重要,可确保在复杂环境中安全高效地导航。虽然最近基于学习的方法&a…...

Vue3:本地启动Vue3项目失败,报not found xxx moudel

一、情况描述 我这边是从git上下载的一份可用代码 是之前在公司上传的 于是,在加clone到本地。继续开发 get到项目后,我先进行了:npm install,也没显示报错。 启动的时候报错。 二、解决 rm -rf node_modules npm cache clean…...

nodejs去除本地文件html字符

说明:我希望用nodejs 写一个小工具,去除本地txt文件中的html字符,去除字符后生成新的文件,同样保存在桌面 文件的具体位置是C:\Users\Administrator\Desktop\file.txt step1:C:\Users\Administrator\WebstormProjects\untitled4\f…...

dify部署

https://github.com/langgenius/dify 介绍 Dify 是一款开源的大语言模型(LLM) 应用开发平台。它融合了后端即服务(Backend as Service)和 LLMOps 的理念,使开发者可以快速搭建生产级的生成式 AI 应用。Dify 内置了构建 LLM 应用所需的关键技…...

【Redis】常用命令汇总

Redis 作为高性能的键值存储数据库,提供了丰富的命令集,主要涵盖 字符串 (String)、哈希 (Hash)、列表 (List)、集合 (Set)、有序集合 (ZSet)、键 (Keys)、Geo(地理位置)、HyperLogLog(基数统计)、Bitmap&a…...

分析TCP三次握手与四次挥手

TCP(传输控制协议)通过三次握手建立连接,四次挥手终止连接,确保数据传输的可靠性。 TCP的三个控制标志位: SYN——用于建立连接,同步序列号。 ACK——用于确认收到的数据。 FIN——用于终止连接。 ISN…...