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

【C++】 Qt-事件(上)(事件、重写事件、事件分发)

文章目录

      • 事件
      • 重写事件
      • 事件分发

事件

事件(event)是由系统或Qt本身在不同的时刻发出的。比如,当用户按下鼠标,敲下键盘,或窗口需要重新绘制的时候,都会发出一个相应的事件。一些事件是在对用户操作做出响应的时候发出,如键盘事件等;另一些事件则是由系统自动发出,如定时器事件(在我们之前写的游戏壳子中用的就是这类事件)。

Qt的事件和信号槽很容易混淆,事件其实也就是所谓的事件驱动,signal由具体对象发出,然后会马上交给connect函数连接的slot进行处理。而对于事件,Qt使用一个**事件队列(windowSystemEventQueue)**对所有发出的事件进行维护,当新的事件产生时,会被追加到事件队列的尾部,前一个事件完成后,取出后面的事件进行处理。但是,必要的时候,Qt的事件也是可以不进入事件队列,而是直接处理的。

如果我们使用组件,我们关心的是信号槽;如果我们自定义组件,我们关心的是事件。

重写事件

一般我们重写某个组件的事件,需要自定义类,继承对应的组件类,重写感兴趣的事件。

新建子类:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NQ3AxlrK-1688187869334)(C++.assets/image-20230619200032369.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mmx0Xx5N-1688187869335)(C++.assets/image-20230619200059528.png)]

然后在代码创建成功后将父类改为QLable。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IhD35y3s-1688187869335)(C++.assets/image-20230619200323735.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eJZlUNye-1688187869336)(C++.assets/image-20230619200434430.png)]

想知道有哪些事件,我们需要转到父类中,模糊搜索event,事件多为虚函数,供我们重写,定义自己的实现规则。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gstro72k-1688187869336)(C++.assets/image-20230619200555877.png)]

我们关注鼠标相关的事件:分别将mousePressEvent,mouseMoveEvent,mouseReleaseEvent三个虚函数(在qt中表现为斜体)重写。

可以在函数的声明后面加上宏Q_DECL_OVERRIDE或关键字override进行校验当前的虚函数是否为重写父类的,如果不是则会报错。

在重写的三个虚函数中,我们需要跟踪鼠标左键在Lable组件的状态。

声明:

public:void mousePressEvent(QMouseEvent *ev) Q_DECL_OVERRIDE;void mouseMoveEvent(QMouseEvent *ev) Q_DECL_OVERRIDE;void mouseReleaseEvent(QMouseEvent *ev) Q_DECL_OVERRIDE;

定义:

void MyLabel::mousePressEvent(QMouseEvent *ev){if(ev->button() == Qt::LeftButton){  //如果按下的键是鼠标左键this->setText(QString("鼠标左键按下:%1,%2").arg(ev->x()).arg(ev->y()));}
}//button:触发当前事件的按钮
//buttons:触发当前事件时,有哪些按键是按下的
void MyLabel::mouseMoveEvent(QMouseEvent *ev){if(ev->buttons() == Qt::LeftButton|Qt::RightButton){  //鼠标左键和右键同时按下且移动this->setText(QString("鼠标左键合右键同时按下且移动"));}else if(ev->buttons() == Qt::NoButton){  //鼠标移动,没有按下任何的按键this->setText(QString("鼠标移动:%1,%2").arg(ev->x()).arg(ev->y()));}
}void MyLabel::mouseReleaseEvent(QMouseEvent *ev){if(ev->button() == Qt::RightButton){  //鼠标右键抬起this->setText(QString("鼠标右键抬起:%1,%2").arg(ev->x()).arg(ev->y()));}
}

自定义的MyLabel类与主窗口上的Label组件绑定。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GYG0EkYg-1688187869336)(C++.assets/image-20230619202211745.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CzA0BYqi-1688187869336)(C++.assets/image-20230619202318093.png)]

然后我们测试,经过测试我们发现基本都能通过,唯有一个当鼠标只移动没按下时没有反应,这是因为我们在他未按下时没有对他进行追踪,所以我们在构造函数中去添加一个函数。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-abnFJqJq-1688187869337)(C++.assets/image-20230619202634123.png)]

这样就可以了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a6DyhAf8-1688187869337)(C++.assets/image-20230619202709370.png)]

事件分发

事件对象创建完毕后,Qt将这个事件传递给QObject::event()函数,event()函数主要用于事件的分发,一般情况下并不直接处理事件,而是将这些事件按照他们不同的类型,分发给不同的事件处理器(event handler)。

如果想在事件分发之前做一些额外的操作或屏蔽掉某些事件,我们也可以重写event()函数。通过event->type()来确定事件的类型。

举例:在窗口添加组件line edit,我们约定其为电话号码,并且只能输入数字最多可输入11位。

这个需求不敢说用信号槽一定不能做,但是一定会很麻烦,所以我们可以在事件分发中去做

我们首先还是要去自定义类,去继承对应的组件类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IxJKCOHx-1688187869337)(C++.assets/image-20230629072253496.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ajzwByEX-1688187869337)(C++.assets/image-20230629072318382.png)]

现在类建完了,那么就要去找需要重写的函数了

我们去父类中去通过模糊搜索event事件,找到我们需要的相关事件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8lmsTs5L-1688187869337)(C++.assets/image-20230629072513696.png)]

将这个事件粘贴到子类中,然后我们还需要找到键盘释放的事件,但我们发现父类中没有,所以我们去爷爷类中寻找

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ue1QzbcL-1688187869338)(C++.assets/image-20230629072911850.png)]

我们找到了键盘释放函数,并且还找到了一个事件分发函数,将这两个函数也放到子类中去重写

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FPXjH8Kw-1688187869338)(C++.assets/image-20230629073104332.png)]

然后将这三个函数在源文件中去定义

事件分发是在事件处理器之前发生的,用来集中接收并分发各种类型的事件

在事件分发函数中去实现拦截非法字符

//事件分发,集中接收并分发各种类型的事件
bool MyLineEdit::event(QEvent *event){if(event->type() == QEvent::KeyPress){  //判断事件类型,如果是键盘按下的事件QKeyEvent * pkey=(QKeyEvent *)event;  //已经做判断了,所以可以强转为具体的事件了if(Qt::Key_0 <= pkey->key() && pkey->key() <= Qt::Key_9 || pkey->key() == Qt::Key_Backspace){  //0~9分发,return QLineEdit::event(event);  //调用父类的分发}else{  //不分发qDebug()<<"event 拦截"<<pkey->key();//return true;  //代表的是:当前事件已经被处理,不需要分发了return false;  //代表:当前事件处理不了,一般会转到父窗口处理}}return QLineEdit::event(event);  //其他类型的事件,仍要继续分发
}

然后要将line edit提升为MyLineEdit

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3NycJuNK-1688187869338)(C++.assets/image-20230629075111671.png)]

然后在键盘按下事件中实现将接收到的数字转为字符串,并显示

此时我们在输入电话号时就只能输入数字了,如果输入字母就会被拦截(英文模式下)

将电话号码存放到类成员属性中

我们再加一个限定条件,让输入的字符串只能小于11位

但是还有一个问题,如果我们输入的电话号码有误,那我们不管点什么都会被拦截,所以要再事件分发函数拦截条件中释放一个删除的口子

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2WARmABn-1688187869338)(C++.assets/image-20230629075637783.png)]

然后在键盘按下函数中做一个判断,如果按下的是退格键,就在结尾删除一位

到现在还没有结束,我们的需求又增加了,为了提高私密性,我们想将中间的四位数字以*的形式显示

所以还要在判断中加上三组判断,如果size小于3就正常输出,如果大于3小于7就显示*,最后大于七位就将前三位正常截取,然后拼接四个 *,在拼接上最后四位,最后再去显示

当然在之前实现尾删除时,最终显示也要显示带*的号码

键盘按下事件的完整实现:

void MyLineEdit::keyPressEvent(QKeyEvent * pkey){if(pkey->key() == Qt::Key_Backspace){  //结尾删除一位m_tel= m_tel.left(m_tel.size()-1);  //保留前面,去除最后一位//this->setText(m_tel);this->setText(this->text().left(this->text().size()-1));}else if(m_tel.size()<11){m_tel += QString::number(pkey->key()-Qt::Key_0);this->setText(m_tel);  //将接收到的数字转换为字符串,并显示if(m_tel.size()<=3){this->setText(m_tel);}else if(3<m_tel.size() && m_tel.size() <=7){QString tel = m_tel.left(3);for(int i=3;i<m_tel.size();i++){tel+="*";}this->setText(tel);}else{QString tel = m_tel.left(3)+"****"+ m_tel.right(m_tel.size()-7);this->setText(tel);}}
}

最后还剩一点,我们此时的电话号码是带*加密的状态,那么我们想把键盘释放事件也利用上,在键盘释放中实现将完整电话号码显示出来,我们约定在回车键抬起时弹出一个弹出框将完整电话号码显示出来

void MyLineEdit::keyReleaseEvent(QKeyEvent *event){//Qt::Key_Return 字母区的回车  Qt::Key_Enter 数字小键盘的回车if(event->key() == Qt::Key_Return){  //如果是回车抬起QMessageBox::information(this,"电话号码",m_tel);}
}

最后,我们还记得之前在输入字母时会默认是中文,如果是中文输入法那么就不会对字母拦截,所以我们想把中文输入法禁用

在构造函数初始时调用一个禁用中文输入法的函数

MyLineEdit::MyLineEdit(QWidget *parent) : QLineEdit(parent)
{this->setAttribute(Qt::WA_InputMethodEnabled,false);  //禁用中文输入法
}

最终窗口显示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aB285ZDP-1688187869338)(C++.assets/image-20230629081834237.png)]

相关文章:

【C++】 Qt-事件(上)(事件、重写事件、事件分发)

文章目录 事件重写事件事件分发 事件 事件&#xff08;event&#xff09;是由系统或Qt本身在不同的时刻发出的。比如&#xff0c;当用户按下鼠标&#xff0c;敲下键盘&#xff0c;或窗口需要重新绘制的时候&#xff0c;都会发出一个相应的事件。一些事件是在对用户操作做出响应…...

k8s部署springboot

前言 首先以SpringBoot应用为例介绍一下k8s的部署步骤。 1.从代码仓库下载代码&#xff0c;比如GitLab&#xff1b; 2.接着是进行打包&#xff0c;比如使用Maven&#xff1b; 3.编写Dockerfile文件&#xff0c;把步骤2产生的包制作成镜像&#xff1b; 4.上传步骤3的镜像到远程…...

备战秋招002(20230704)

文章目录 前言一、今天学习了什么&#xff1f;二、关于问题的答案1.线程池2.synchronized关键字3、volatile 总结 前言 提示&#xff1a;这里为每天自己的学习内容心情总结&#xff1b; Learn By Doing&#xff0c;Now or Never&#xff0c;Writing is organized thinking. …...

游泳买耳机买什么的比较好,列举几款实战性好的游泳耳机

对于运动用户来说&#xff0c;在运动时都会选择听一些节奏感比较强的音乐&#xff0c;让自己运动是更有活力。现在已经是三伏天中的前伏期间&#xff0c;不少人会选择在三伏天的日子里进行减肥瘦身&#xff0c;耳游泳已经成为很多人都首选运动&#xff0c;游泳是非常好的有氧运…...

【无线传感器】使用 MATLAB和 XBee连续监控温度传感器无线网络研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

Java基础-多线程JUC-生产者和消费者

1. 生产者与消费者 实现线程轮流交替执行的结果&#xff1b; 实现线程休眠和唤醒均要使用到锁对象&#xff1b; 修改标注位&#xff08;foodFlag&#xff09;&#xff1b; 代码实现&#xff1a; public class demo11 {public static void main(String[] args) {/*** 需求&#…...

day2 QT按钮与容器

目录 按钮 1、QPushButton 2、QToolButton 3、QRadioButton 4、QCheckBox 示例 容器 ​编辑 1. QGroupBox&#xff08;分组框&#xff09; 2. QScrollArea&#xff08;滚动区域&#xff09; 3. QToolBox&#xff08;工具箱&#xff09; 4. QTabWidget&#xff08;选…...

JPA 批量插入较大数据 解决性能慢问题

JPA 批量插入较大数据 解决性能慢问题 使用jpa saveAll接口的话需要了解原理&#xff1a; TransactionalOverridepublic <S extends T> List<S> saveAll(Iterable<S> entities) {Assert.notNull(entities, "Entities must not be null!");List<…...

为啥离不了 linux

Linux与Windows都是十分常见的电脑操作系统&#xff0c;相信你对它们二者都有所了解&#xff01;在你的使用过程中&#xff0c;是否有什么事让你觉得在Linux上顺理成章&#xff0c;换到Windows上就令你费解&#xff1f;亦或者关于这二者你有任何想要分享的&#xff0c;都可以在…...

基于分形的置乱算法和基于混沌系统的置乱算法哪种更安全?

在信息安全领域中&#xff0c;置乱算法是一种重要的加密手段&#xff0c;它可以将明文进行混淆和打乱&#xff0c;从而实现保密性和安全性。常见的置乱算法包括基于分形的置乱算法和基于混沌系统的置乱算法。下面将从理论和实践两方面&#xff0c;对这两种置乱算法进行比较和分…...

pve使用cloud-image创建ubuntu模板

首先连接pve主机的终端 下载ubuntu22.04的cloud-image镜像 wget -P /opt https://mirrors.cloud.tencent.com/ubuntu-cloud-images/jammy/current/jammy-server-cloudimg-amd64.img创建虚拟机&#xff0c;id设为9000&#xff0c;使用VirtIO SCSI控制器 qm create 9000 -core…...

shiro入门

1、概述 Apache Shiro 是一个功能强大且易于使用的 Java 安全(权限)框架。借助 Shiro 您可以快速轻松地保护任何应用程序一一从最小的移动应用程序到最大的 Web 和企业应用程序。 作用&#xff1a;Shiro可以帮我们完成 &#xff1a;认证、授权、加密、会话管理、与 Web 集成、…...

开源 sysgrok — 用于分析、理解和优化系统的人工智能助手

作者&#xff1a;Sean Heelan 在这篇文章中&#xff0c;我将介绍 sysgrok&#xff0c;这是一个研究原型&#xff0c;我们正在研究大型语言模型 (LLM)&#xff08;例如 OpenAI 的 GPT 模型&#xff09;如何应用于性能优化、根本原因分析和系统工程领域的问题。 你可以在 GitHub …...

Gitlab保护分支与合并请求

目录 引言 1、成员角色指定 1、保护分支设置 2、合并请求 引言 熟悉了Git工作流之后&#xff0c;有几个重要的分支&#xff0c;如Master(改名为Main)、Develop、Release分支等&#xff0c;是禁止开发成员随意合并和提交的&#xff0c;在此分支上的提交和推送权限仅限项目负责…...

ad18学习笔记九:输出文件

一般来说提供给板卡厂的文件里要包括以下这些文件 1、装配图 2、bom文件 3、gerber文件 4、转孔文件 5、坐标文件 6、ipc网表 AD_PCB&#xff1a;Gerber等各类文件的输出 - 哔哩哔哩 原点|钻孔_硬件设计AD 生成 Gerber 文件 1、装配图 如何输出装配图&#xff1f; 【…...

PostgreSQL 内存配置 与 MemoryContext 的生命周期

PostgreSQL 内存配置与MemoryContext的生命周期 PG/GP 内存配置 数据库可用的内存 gp_vmem 整个 GP 数据库可用的内存 gp_vmem&#xff1a; >>> RAM 128 * GB >>> gp_vmem ((SWAP RAM) - (7.5*GB 0.05 * RAM)) / 1.7 >>> print(gp_vmem / G…...

vue3 组件间通信的方式(setup语法糖写法)

vue3 组件间通信的方式(setup语法糖写法) 1. Props方式 该方式用于父传子&#xff0c;父组件以数据绑定的形式声明要传递的数据&#xff0c;子组件通过defineProps()方法创建props对象&#xff0c;即可拿到父组件传来的数据。 // 父组件 <template><div><son…...

【Cache】Rsync远程同步

文章目录 一、rsync 概念二、rysnc 服务器部署1. 环境配置2. rysnc 同步源服务器2.1 安装 rsync2.2 建立 rsyncd.conf 配置文件2.3 创建数据文件&#xff08;账号密码&#xff09;2.4 启动服务2.5 数据配置 3. rysnc 客户端3.1 设置同步方法一方法二 3.2 免交互设置 4. rysnc 认…...

Gitlab升级报错一:rails_migration[gitlab-rails] (gitlab::database_migrations line 51)

Gitlab-ce从V14.0.12升级到V14.3.6或V14.10.5时报错&#xff1a;如下图&#xff1a; 解决办法&#xff1a; 先停掉gitlab: gitlab-ctl stop 单独启动数据库&#xff0c;如果不单独启动数据库&#xff0c;就会报以上错误 sudo gitlab-ctl start postgresql 解决办法&#x…...

chatGPT流式回复是怎么实现的

chatGPT流式回复是怎么实现的 先说结论&#xff1a; chatGPT的流式回复用的就是HTTP请求方案中的server-send-event流式接口&#xff0c;也就是服务端向客户端推流数据。 那eventStream流式接口怎么实现呢&#xff0c;下面就进入正题&#xff01; 文章目录 chatGPT流式回复…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

适应性Java用于现代 API:REST、GraphQL 和事件驱动

在快速发展的软件开发领域&#xff0c;REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名&#xff0c;不断适应这些现代范式的需求。随着不断发展的生态系统&#xff0c;Java 在现代 API 方…...

学习一下用鸿蒙​​DevEco Studio HarmonyOS5实现百度地图

在鸿蒙&#xff08;HarmonyOS5&#xff09;中集成百度地图&#xff0c;可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API&#xff0c;可以构建跨设备的定位、导航和地图展示功能。 ​​1. 鸿蒙环境准备​​ ​​开发工具​​&#xff1a;下载安装 ​​De…...