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

news2024/9/30 0:28:33

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_OBJECT
			public:
			    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_OBJECT
			public:
			    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_OBJECT
			public:
			    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_NAMESPACE
			namespace Ui { class Widget; }
			QT_END_NAMESPACE
			
			class Widget : public QWidget
			{
			    Q_OBJECT
			
			public:
			    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_NAMESPACE
			namespace Ui { class Widget; }
			QT_END_NAMESPACE
			
			class Widget : public QWidget
			{
			    Q_OBJECT
			
			public:
			    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();   // ±120
			    if(event->delta() > 0) {
			        qDebug() << "滚轮往前" << x;
			    }
			    else {
			        qDebug() << "滚轮往后" << x;
			    }
			}

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

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

相关文章

【多线程-从零开始-叁】线程的核心操作

一、创建一个线程-start() start 和 run 的区别&#xff1a;&#xff08;经典面试题&#xff09; run 描述了线程要执行的任务&#xff0c;也可以称为“线程的入口”此处 start 会根据不同的系统&#xff0c;分别调用不同的 API&#xff0c;来执行系统函数&#xff0c;在系统…

原生多模态跟GPT聊天部分测试,大家都用他来做什么;字节推出AI音乐产品-海绵音乐,可以媲美Udio和Suno

✨ 1: 跟GPT聊天 原生多模态跟GPT聊天部分测试&#xff0c;大家都用他来做什么。 说各个国家的语言&#xff0c;例如普通话&#xff0c;或者是广东话等。 ChatGPT担任富有激情的足球比赛解说员 使用新的高级语音模式 视觉&#xff0c;进行实时日语翻译&#xff01; 地址&…

Java编程规范 空格

public static void main(String[] args) { // 缩进4 个空格 String say "hello"; // 运算符的左右必须有一个空格 int flag 0; // 关键词if 与括号之间必须有一个空格&#xff0c;括号内的f与左括号&#xff0c;0与右括号不需要空格 if (flag 0) { System…

秃姐学AI系列之:模型选择 | 欠拟合和过拟合 | 权重衰退

目录 训练误差 泛化误差 验证数据集和测试数据集 验证数据集 Validation Dataset&#xff1a; 测试数据集&#xff1a; K-则交叉验证 总结 过拟合和欠拟合 模型容量 模型容量的影响 估计模型容量 数据复杂度 总结 权重衰退 weight decay 使用均方范数作为硬性…

【八】Zookeeper3.7.1集成Hadoop3.3.4集群安装

文章目录 1.基本原理2.下载并解压ZooKeeper3.配置环境变量4.配置ZooKeeper5.创建数据目录并初始化myid6.启动ZooKeeper7.配置ZooKeeper集成到Hadoop8.重启Hadoop9.ZooKeeper状态检查 1.基本原理 ZooKeeper 是一个分布式协调服务&#xff0c;用于分布式系统中管理配置信息、命名…

51单片机—智能垃圾桶(定时器)

一. 定时器 1. 简介 C51中的定时器和计数器是同一个硬件电路支持的&#xff0c;通过寄存器配置不同&#xff0c;就可以将他当做定时器或者计数器使用。 确切的说&#xff0c;定时器和计数器区别是致使他们背后的计数存储器加1的信号不同。当配置为定时器使用时&#xff0c;每…

vue3 手写日历组件

找了很久vue3的element样式一直没办法修改实现。只能手写日历了。借鉴了一些大佬的代码 调用&#xff1a; 再要使用的地方引入 import calendarelement from ./calendarelement.vue //日历组件 <div > <calendarelement /> //日历</div> 效果&#…

押金原路退回系统在医院中应用,一键操作秒到账 押金+身份证+电子押金单

一、医院押金管理必要性 保障医疗服务的连续性&#xff1a;患者缴纳押金能够确保在治疗过程中&#xff0c;医院有足够的资金来提供必要的医疗服务、药品和设备&#xff0c;不会因为费用问题而中断治疗。例如&#xff0c;在紧急手术或需要持续使用昂贵药物的情况下&#xff0c;…

【Vue3】组件通信之$attrs

【Vue3】组件通信之$attrs 背景简介开发环境开发步骤及源码总结 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗的…

开发在线客服系统新的宣传推广站【微客客服】

打造一个软件宣传官网&#xff0c;这事儿可不简单。咱们得先搞清楚&#xff0c;这个网站要给谁看&#xff0c;要传达啥信息&#xff0c;需要哪些功能。 我们网站是宣传【在线客服系统】的&#xff0c;所以需要把主要功能展示清楚 在线网址&#xff1a;https://weikefu.com.cn 然…

Python面试宝典第27题:全排列

题目 给定一个不含重复数字的数组nums&#xff0c;返回其所有可能的全排列 。备注&#xff1a;可以按任意顺序返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]] 示例 2&#xff1a; 输…

Qt之Gui

组件依赖关系 应用 #mermaid-svg-GADicZtZJRVVUeiF {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GADicZtZJRVVUeiF .error-icon{fill:#552222;}#mermaid-svg-GADicZtZJRVVUeiF .error-text{fill:#552222;stroke:#…

【Spark计算引擎----第三篇(RDD)---《深入理解 RDD:依赖、Spark 流程、Shuffle 与缓存》】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;我是书生♡&#xff0c;本阶段和大家一起分享和探索大数据技术Spark—RDD&#xff0c;本篇文章主要讲述了&#xff1a;RDD的依赖、Spark 流程、Shuffle 与缓存等等。欢迎大家一起探索讨论&#xff01;&#xff0…

【Gold菜鸟】Linux知识回忆(8)——进程和计划任务

前言 这部分让我们来继续了解Linux中进程和计划任务的相关知识吧~ 相关技术交流欢迎添加VX: wenjinworkon 目录 进程和内存管理 什么是进程 进程结构 进程相关概念 物理地址空间和虚拟地址空间 用户和内核空间 进程使用内存问题 进程状态 内存淘汰数据机制&#xff1a;…

数学建模评价类—Topsis法

目录 文章目录 前言 切记&#xff1a;以下内容仅用于参考理解&#xff0c;不可用于数模竞赛&#xff01;&#xff01;&#xff01; 一、Topsis的基本原理 二、Topsis的建模过程 1.判断矩阵是否需要正向化 2.原始矩阵正向化 3.矩阵标准化 4.计算距离&#xff0c;给出得…

Can Large Language Models Provide Feedback to Students? A Case Study on ChatGPT

文章目录 题目摘要相关工作方法结果讨论意义 题目 大型语言模型能为学生提供反馈吗&#xff1f;ChatGPT 案例研究 论文地址&#xff1a;https://ieeexplore.ieee.org/abstract/document/10260740 摘要 摘要——教育反馈已被广泛认为是提高学生学习能力的有效方法。然而&#x…

Python | Leetcode Python题解之第322题零钱兑换

题目&#xff1a; 题解&#xff1a; class Solution:def coinChange(self, coins: List[int], amount: int) -> int:dp [float(inf)] * (amount 1)dp[0] 0for coin in coins:for x in range(coin, amount 1):dp[x] min(dp[x], dp[x - coin] 1)return dp[amount] if d…

Python的if语句及其运用

一、条件测试 每条if语句的核心都是一个值为True或False的表达式&#xff0c;这种表达式称为条件测试。如果测试的条件满足if语句则为True&#xff0c;接着执行if里的语句&#xff1b;如果测试的条件不满足if语句则为False&#xff0c;则不执行if里的语句。 1.1、检查是否相等…

C++ | Leetcode C++题解之第322题零钱兑换

题目&#xff1a; 题解&#xff1a; class Solution { public:int coinChange(vector<int>& coins, int amount) {int Max amount 1;vector<int> dp(amount 1, Max);dp[0] 0;for (int i 1; i < amount; i) {for (int j 0; j < (int)coins.size();…

二叉树(真题)

1.用非递归遍历求二叉树结点个数【计学2020】 算法思想:用先序非递归遍历 当前指针不为空或栈不为空进行循环&#xff1b; 当前指针不为空访问当前结点&#xff0c;当前节点入栈&#xff0c;进入左子树 当前指针为空&#xff0c;栈顶元素出栈&#xff08;回溯&#xff09;&…