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

【QT】鼠标按键事件 - QMouseEvent QKeyEvent

qt 事件

  • 事件
    • 1. 事件概念
    • 2. 事件的处理
    • 3. 按键事件
      • (1)单个按键
      • (2)组合按键
    • 4. 鼠标事件
      • (1)鼠标单击事件
      • (2)鼠标释放事件
      • (3)鼠标双击事件
      • (4)鼠标移动事件
      • (5)滚轮事件

事件

1. 事件概念

事件是应用程序内部或者外部产生的事情或者动作的统称。在 Qt 中使用⼀个对象来表⽰⼀个事件。所有的 Qt 事件均继承于抽象类 QEvent。事件是由系统或者 Qt 平台本⾝在不同的时刻发出的。当用户按下⿏标、敲下键盘,或者是窗⼝需要重新绘制的时候,都会发出⼀个相应的事件。⼀些事件是在用户操作时发出,如键盘事件、⿏标事件等,另⼀些事件则是由系统本⾝⾃动发出,如定时器事件。常见的 Qt 事件如下:

在这里插入图片描述

常见事件描述:

在这里插入图片描述

2. 事件的处理

事件处理⼀般常用的方法为:重写相关的 Event 函数。

在 Qt 中,几乎所有的 Event 函数都是虚函数,所以可以重新实现。如:在实现⿏标的进⼊和离开事件时,直接重新实现 enterEvent() 和 leaveEvent() 即可。enterEvent()leaveEvent() 函数原型如下:

在这里插入图片描述

代码示例1:

1、新建 Qt 项目,基类选择 QWidget,同时勾选 UI 界面文件;
2、设计 UI 文件,在 ui 文件中拖入一个 Label,给 Label 加一个边界框,方便观察鼠标进入和移动,如下图;

在这里插入图片描述

3、在项目中新添加⼀个类:MyLabel;

先选中项⽬名称 qt_event,点击⿏标右键,选择 add new … ,弹出如下对话框:

在这里插入图片描述

接下来弹出以下界面,按照下面的操作即可:

在这里插入图片描述

此时项⽬中会新添加以下两个文件件:

在这里插入图片描述

4、将 enterEvent() 添加到项目文件 “mylabel.h” 中:

			#ifndef MYLABEL_H#define MYLABEL_H#include <QWidget>class MyLabel : public QWidget{Q_OBJECTpublic:explicit MyLabel(QWidget *parent = nullptr);// 鼠标进入事件void enterEvent(QEvent* event);signals:};#endif // MYLABEL_H

5、在 mylabel.cpp 中重写 enterEvent() 方法:

			#include "mylabel.h"#include <QDebug>MyLabel::MyLabel(QWidget *parent) : QWidget(parent){}void MyLabel::enterEvent(QEvent *event){qDebug() << "鼠标进入事件";}

6、在 UI 文件中选中 Label,右键 ------> 提升为…,当点击 "提升为… " 之后,弹出如下对话框,按照顺序添加即可:

在这里插入图片描述

7、修改基类,到 mylabel.cpp 和 mylabel.h 中将 Widget 改为 QLabel:

mylabel.h:

			#ifndef MYLABEL_H#define MYLABEL_H#include <QLabel>class MyLabel : public QLabel{Q_OBJECTpublic:explicit MyLabel(QWidget *parent = nullptr);// 鼠标进入事件void enterEvent(QEvent* event);signals:};#endif // MYLABEL_H

mylabel.cpp:

			#include "mylabel.h"#include <QDebug>MyLabel::MyLabel(QWidget *parent) : QLabel(parent){}void MyLabel::enterEvent(QEvent *event){qDebug() << "鼠标进入事件";}

8、执行效果如下:当⿏标进⼊设计好的标签之后,就会在应⽤程序输出栏中打印:⿏标进⼊:

在这里插入图片描述

代码示例2: 当⿏标点击时,获取对应的坐标值;

1、在上述示例的基础上,在 mylabel.h 中声明 mousePressEvent() 方法:

			class MyLabel : public QLabel{Q_OBJECTpublic:explicit MyLabel(QWidget *parent = nullptr);// 鼠标进入事件void enterEvent(QEvent* event);// 鼠标移动事件void mousePressEvent(QMouseEvent* ev);signals:};

2、在 mylabel.cpp 中重写 mousePressEvent() 方法:

			#include "mylabel.h"#include <QDebug>#include <QMouseEvent>MyLabel::MyLabel(QWidget *parent) : QLabel(parent){}void MyLabel::enterEvent(QEvent *event){qDebug() << "鼠标进入事件";}void MyLabel::mousePressEvent(QMouseEvent *ev){// qt中的格式化字符串QString str1 = QString("鼠标按下了 x = %1, y = %2").arg(ev->x()).arg(ev->y());qDebug() << str1;}

实现效果如下:

在这里插入图片描述

示例代码3: ⿏标左键点击时,打印对应的坐标值,⿏标右键点击时,打印基于屏幕的坐标

			void MyLabel::mousePressEvent(QMouseEvent *ev){// 鼠标左键if(ev->button() == Qt::LeftButton) {// x, y 为基于窗口的坐标QString str = QString("鼠标左键: x = %1, y = %2").arg(ev->x()).arg(ev->y());qDebug() << str.toUtf8().data();}// 鼠标右键if(ev->button() == Qt::RightButton) {// globalX, globalY 为基于屏幕的坐标QString str = QString("鼠标左键: x = %1, y = %2").arg(ev->globalX()).arg(ev->globalY());qDebug() << str.toUtf8().data();}}

3. 按键事件

Qt 中的按键事件是通过 QKeyEvent 类来实现的。当键盘上的按键被按下或者被释放时,键盘事件便会触发。在帮助文档中查找 QKeyEvent 类,查找按键事件中所有的按键类型,在帮助文档中输⼊:Qt::Key,如下图:

在这里插入图片描述

(1)单个按键

代码示例:当某个按键被按下时,输出:某个按键被按下了;

1、新建项目,在头文件 “widget.h” 中声明虚函数 keyPressEvent();如下:

			#ifndef WIDGET_H#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACEnamespace Ui { class Widget; }QT_END_NAMESPACEclass Widget : public QWidget{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();// 声明按键按下事件void keyPressEvent(QKeyEvent* event);private:Ui::Widget *ui;};#endif // WIDGET_H

2、在 “widget.cpp” 文件中重写 keyPressEvent() 虚函数;

			#include "widget.h"#include "ui_widget.h"#include <QKeyEvent>#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget){ui->setupUi(this);}Widget::~Widget(){delete ui;}void Widget::keyPressEvent(QKeyEvent *event){if(event->key() == Qt::Key_A) {qDebug() << "A按键被按下";}}

(2)组合按键

在 Qt 助手中搜索:Qt::KeyboardModifier,如下图示:

在这里插入图片描述

Qt::KeyboardModifier 中定义了在处理键盘事件时对应的修改键。在 Qt 中,键盘事件可以与修改键一起使用,以实现⼀些复杂的交互操作。KeyboardModifier 中修改键的具体描述如下:

在这里插入图片描述

示例代码:

			void Widget::keyPressEvent(QKeyEvent *event){// 组合按键if(event->modifiers() == Qt::ControlModifier) // 判断是否按下ctrl键{if(event->key() == Qt::Key_A) {     // 判断 A 键是否按下qDebug() << "ctrl + A 被按下";}}}

4. 鼠标事件

在 Qt 中,⿏标事件是⽤ QMouseEvent 类来实现的。当在窗⼝中按下⿏标或者移动⿏标时,都会产⽣⿏标事件。

利⽤ QMouseEvent 类可以获取⿏标的哪个键被按下了以及⿏标的当前位置等信息。在 Qt 帮助⽂档中查找 QMouseEvent 类如下图⽰:

在这里插入图片描述

(1)鼠标单击事件

在 Qt 中,⿏标按下是通过虚函数 mousePressEvent() 来捕获的。 mousePressEvent() 函数原型如下:

		[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event)

⿏标左右键及滚的表示如下:

		Qt::LeftButton ⿏标左键Qt::RightButton ⿏标右键Qt::MidButton ⿏标滚轮

示例代码1:

1、在 “widget.h” 头⽂件中声明⿏标按下事件;

			#ifndef WIDGET_H#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACEnamespace Ui { class Widget; }QT_END_NAMESPACEclass Widget : public QWidget{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();// 鼠标按下事件void mousePressEvent(QMouseEvent* event);private:Ui::Widget *ui;};#endif // WIDGET_H

2、在 “widget.cpp” ⽂件中重新实现 mousePressEvent() 函数;

			#include "widget.h"#include "ui_widget.h"#include <QMouseEvent>#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget){ui->setupUi(this);}Widget::~Widget(){delete ui;}void Widget::mousePressEvent(QMouseEvent *event){if(event->button() == Qt::LeftButton) {qDebug() << "鼠标左键被按下";}}

修改成当鼠标滚轮被按下才打印:

			void Widget::mousePressEvent(QMouseEvent *event){if(event->button() == Qt::MidButton) {qDebug() << "鼠标滚轮被按下";}}

(2)鼠标释放事件

⿏标释放事件是通过虚函数 mouseReleaseEvent() 来捕获的。 mouseReleaseEvent() 函数原型如下:

		[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event)

示例代码:

			void Widget::mouseReleaseEvent(QMouseEvent *event){if(event->button() == Qt::LeftButton) {qDebug() << "鼠标左键被释放";}}

(3)鼠标双击事件

⿏标双击事件是通过虚函数:mouseDoubleClickEvent() 来实现的。 mouseDoubleClickEvent() 函数原型如下:

		[virtual protected] void QWidget::mouseDoubleClickEvent(QMouseEvent *event)

示例代码:

		void Widget::mouseDoubleClickEvent(QMouseEvent *event){if(event->button() == Qt::LeftButton) {qDebug() << "鼠标左键被双击";}}

(4)鼠标移动事件

⿏标移动事件是通过虚函数:mouseMoveEvent() 来实现的。同时为了实时捕获⿏标位置信息,需要通过函数 setMouseTracking() 来追踪⿏标的位置。mouseMoveEvent() 函数原型如下:

		[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event)

setMouseTracking() 函数原型如下:

		void setMouseTracking(bool enable)

说明:setMouseTracking() 函数默认是 false,需要设置为 true,才能实时捕获⿏标位置信息。否则只有当⿏标按下时才能捕获其位置信息。

示例代码:

			Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget){ui->setupUi(this);// 设置鼠标追踪状态setMouseTracking(true);}void Widget::mouseMoveEvent(QMouseEvent *event){qDebug() << "[" << event->x() << ", " << event->y() << "]";}

(5)滚轮事件

在 Qt 中,⿏标滚轮事件是通过 QWheelEvent 类来实现的。滚轮滑动的距离可以通过 delta() 函数获取。delta() 函数原型如下:

		int QGraphicsSceneWheelEvent::delta() const

其中返回值代表滚轮滑动的距离。正数表示滚轮相对于用户向前滑动,负数表示滚轮相对于用户向后滑动。

代码示例:

			#include <QWheelEvent>void Widget::wheelEvent(QWheelEvent *event){static int x = 0;x += event->delta();   // ±120if(event->delta() > 0) {qDebug() << "滚轮往前" << x;}else {qDebug() << "滚轮往后" << x;}}

相关文章:

【QT】鼠标按键事件 - QMouseEvent QKeyEvent

qt 事件 事件1. 事件概念2. 事件的处理3. 按键事件&#xff08;1&#xff09;单个按键&#xff08;2&#xff09;组合按键 4. 鼠标事件&#xff08;1&#xff09;鼠标单击事件&#xff08;2&#xff09;鼠标释放事件&#xff08;3&#xff09;鼠标双击事件&#xff08;4&#x…...

纯手工在内网部署一个Docker私有仓库

纯手工在内网部署一个Docker私有仓库 下载Docker仓库的镜像上传仓库的镜像导入仓库的镜像启动仓库镜像配置客户端的Docker上传镜像到本地仓库从本地仓库拉取镜像 下载Docker仓库的镜像 这个镜像不太好找&#xff0c;有需要的可以从下面的地址中下载。 通过百度网盘分享的文件…...

农林经济管理学报

《农林经济管理学报》是由江西省教育厅主管、江西农业大学主办、北京大学中国农业政策研究中心和中国人民大学农业与农村发展学院学术支持的农林经管类学术双月刊&#xff0c;以主要刊载农林经济政策与理论&#xff0c;反映农林经济管理前沿动态和研究成果&#xff0c;开展学术…...

【初阶数据结构题目】16.用队列实现栈

用队列实现栈 点击链接答题 思路&#xff1a; 出栈&#xff1a;找不为空的队列&#xff0c;将size-1个数据导入到另一个队列中。 入栈&#xff1a;往不为空队列里面插入数据 取栈顶元素&#xff1a; 例如&#xff1a; 两个队列&#xff1a; Q1&#xff1a;1 2 3Q2&#xff1a;…...

使用 OpenAI Whisper v2 模型进行中英文混合语音识别

https://huggingface.co/openai/whisper-large-v2 使用 OpenAI Whisper 模型进行中英文混合语音识别 在本篇博客中,我们将详细介绍如何使用 OpenAI 的 Whisper 模型进行中英文混合语音识别,并设置 Hugging Face 的缓存路径。 简介 Whisper 是 OpenAI 提供的一个强大的自动…...

代码随想录算法训练营day37|动态规划part05

完全背包问题&#xff1b; 第一题&#xff1a;518. Coin Change II class Solution {public int change(int amount, int[] coins) {//递推表达式int[] dp new int[amount 1];//初始化dp数组&#xff0c;表示金额为0时只有一种情况&#xff0c;也就是什么都不装dp[0] 1;fo…...

Git 如何提交代码

一. 简介 前面几篇文章简单学习了 git常用命令&#xff0c;文章如下&#xff1a; Git使用过程中涉及的几个区域-CSDN博客 Git常用命令的使用-CSDN博客 本文学习一下 如何使用 git命令&#xff0c;将本地代码提交到远程仓库。 二. 使用 git命令将本地代码提交到远程仓库中 …...

SpringBoot-application.properties为对象赋值

简单对象赋值 第一种方式 首先让该Bean交由Spring管理,然后加上ConfigurationProperties(prefix"前缀") <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId>&l…...

Head First设计模式学习笔记

Head First设计模式学习笔记 大家好&#xff0c;我是微赚淘客系统3.0的小编&#xff0c;是个冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 一、策略模式 策略模式定义了算法族&#xff0c;分别封装起来&#xff0c;让它们之间可以互相替换&#xff0c;此模式让…...

240806-RHEL 无法通过 ssh username@ip 远程连接,报错:Connection closed by ip port 22

A. 原因排查 遇到这个错误通常意味着 SSH 服务可能在目标主机上没有正常运行&#xff0c;或有防火墙/网络配置问题。以下是一些排查步骤&#xff1a; 检查 SSH 服务状态&#xff1a; 确认 SSH 服务是否正在目标主机上运行。 sudo systemctl status sshd重启 SSH 服务&#xff…...

C语言:复读机2种写法(输入什么就输出什么)

&#xff08;1&#xff09;题目&#xff1a;输入什么内容&#xff0c;输出就是什么内容&#xff0c;遇到"#"为止。输入一个随便的字符 &#xff08;2&#xff09;代码&#xff1a; 【1】getchar()和putchar() #include "stdio.h"int main() {char ch;pr…...

PySide6/PyQT学习笔记(很杂)

QGroupBox样式&#xff1a;科技机甲 QGroupBox { border: 2px solid #333; /* 深色边框&#xff0c;类似金属质感 */ border-radius: 8px; /* 轻微的圆角 */ background-color: #222; /* 暗色背景&#xff0c;模拟机甲内部或科技界面 */ color: #fff; /* 字体颜色为白色&a…...

学习笔记-JWT 保持登录状态

目录 一、解析 token 1. 在 JWT 工具类添加解析 token 的方法 2. 在 Controller 添加获取用户数据的方法 二、获取用户信息 1. 发起 axios 请求用户信息 2. 在路由守卫中调用方法 3. 使用 三、token 时效性 1. 设置 token 过期时间 2. 判断 token 是否过期 3. 在拦截…...

React 性能优化

使用 useMemo 缓存数据 &#xff08;类似 vue 的 computed&#xff09;使用 useCallback 缓存函数异步组件 ( lazy )路由懒加载( lazy )服务器渲染 SSR用 CSS 模拟 v-show 循环渲染添加 key使用 Fragment &#xff08;空标签&#xff09;减少层级 不在JSX 中定义函数&#xff0…...

后端常见问题及深度解决方案

&#x1f41f;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢编程&#x1fab4; &#x1f421;&#x1f419;个人主页&#x1f947;&#xff1a;Aic山鱼 &#x1f420;WeChat&#xff1a;z7010cyy &#x1f988;系列专栏&#xff1a;&#x1f3de;️ 前端-JS基础专栏✨前…...

C:野指针介绍(定义、危害、规避)以及野指针与空指针的区分

目录 1、野指针 1.1 野指针的成因 1.指针未初始化 2.指针越界访问 3.指针指向的空间释放 1.2 野指针的危害 1.3 如何规避野指针 1. 指针初始化 2. 小心指针越界 3.指针变量不使用就及时赋上NULL 4. 指针使用前检查是否是空指针 5. 避免返回局部变量的地址 1.4 区…...

vue中v-html 后端返回html + script js中click事件不生效

效果图&#xff1a; 需求&#xff1a;点击加号执行后端返回的script中的代码 后端返回的html&#xff1a; <!DOCTYPE html> <html langzh> <head> <title>xxx</title> <style>body{font-size: 14px}p{text-indent: 30px;}textarea{width…...

介绍maven生命周期-水温

Maven生命周期是指一系列的构建阶段&#xff0c;包括项目的清理、编译、测试、打包、部署等。Maven通过定义生命周期来规范项目构建过程&#xff0c;使得开发人员可以方便地执行一系列的构建任务。 Maven的生命周期分为三个阶段&#xff1a; clean生命周期&#xff1a;主要用…...

spring boot3.x快速入门

下一篇&#xff1a;Spring Boot 3.x gradle脚手架工程build.gradle详解 本教程将基于gradle项目构建工具来快速构建一个spring boot 3.x的最简单的web应用&#xff0c;其中涉及各种构建技巧和细节&#xff0c;希望能帮到初学者~ 文章目录 先决条件JDK17gradle全局配置 gradle项…...

JavaWeb之servlet关于Ajax实现前后端分离

一、什么是Ajax: AJAX Asynchronous JavaScript and XML&#xff08;异步的 JavaScript 和 XML&#xff09;。 AJAX 不是新的编程语言&#xff0c;而是一种使用现有标准的新方法。 AJAX 最大的优点是在不重新加载整个页面的情况下&#xff0c;可以与服务器交换数据并更新部…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...