【Qt】事件

目录

一、介绍

二、进入离开事件

三、鼠标事件

3.1 鼠标单击事件 

3.2 鼠标释放事件

3.3 鼠标双击事件

3.4 鼠标移动事件

3.5 滚轮事件

四、按键事件

4.1 单个按键

4.2 组合按键

五、定时器

5.1 QTimerEvent类 

5.2 QTimer类

5.3 获取系统日期及时间

六、窗口移动和大小改变事件

七、事件分发器

八、事件过滤器


一、介绍

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

常见的Qt事件如下:

二、进入离开事件

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

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

enterEvent() 和 leaveEvent() 函数原型如下:

代码示例

新建Qt项目,基类选择QWidget,同时勾选UI界面文件,如下图示:

设计UI文件,如下图示:

在项目中新添加一个类:MyLabel,先选中项目名称QEvent,点击鼠标右键,选择add new...,弹出如下对话框:

选择:Choose....,弹出如下界面:

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

项目文件"mylabel.h"

重写enterEvent()方法

在UI文件中选中Label,右键 -> 提升为...

当点击"提升为..."之后,弹出如下对话框:

修改基类

三、鼠标事件

在Qt中,鼠标事件是用QMouseEvent类来实现的。当在窗口中按下鼠标或者移动鼠标时,都会产生鼠标事件。利用QMouseEvent类可以获取鼠标的哪个键被按下了以及鼠标的当前位置等信息

在Qt帮助文档中查找QMouseEvent类,如下图示:

3.1 鼠标单击事件 

在Qt中,鼠标按下是通过虚函数mousePressEvent()来捕获的

mousePressEvent()函数原型如下: 

[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event)
  • Qt::LeftButton        鼠标左键
  • Qt::RightButton        鼠标右键
  • Qt::MidButton        鼠标滚轮

代码示例:mousePressEvent()

在上述代码的基础上(进入离开事件),在mylabel.h中声明mousePressEvent()方法

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

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

3.2 鼠标释放事件

鼠标释放事件是通过虚函数mouseReleaseEvent()来捕获的

mouseReleaseEvent()函数原型如下:

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

代码示例:鼠标左键释放

3.3 鼠标双击事件

鼠标双击事件是通过虚函数:mouseDoubleClickEvent()来实现的

mouseDoubleClickEvent()函数原型如下:

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

代码示例:鼠标双击左键

3.4 鼠标移动事件

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

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

注意:

setMouseTracking()函数默认是false,需要设置为true,才能实时捕获鼠标位置信息。否则只有当鼠标按下时才能捕获其位置信息。一般情况下不会开启,若用户鼠标移动过快,会导致资源消耗较大

代码示例:追踪鼠标移动

3.5 滚轮事件

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

int QGraphicsSceneWheelEvent::delta() const

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

代码示例

四、按键事件

Qt中的按键事件是通过QKeyEvent类来实现的。当键盘上的按键被按下或者被释放时,键盘事件便
会触发

4.1 单个按键

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

新建项目,在头文件"widget.h"中声明虚函数keyPressEvent()

在"widget.cpp"文件中重写keyPressEvent()虚函数

4.2 组合按键

在Qt助手中搜索:Qt::KeyboardModifier

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

KeyboardModifier中修改键的具体描述如下:

代码示例:Ctrl + A

五、定时器

Qt中在进行窗口程序的处理过程中,经常要周期性的执行某些操作,或者制作一些动画效果,使用定时器就可以实现。所谓定时器就是在间隔一定时间后,去执行某一个任务。定时器在很多场景下都会使用到,如弹窗自动关闭之类的功能等

Qt中的定时器分为 QTimerEvent 和 QTimer 这2个类:

  • QTimerEvent类用来描述一个定时器事件。在使用时需要通过startTimer()函数来开启一个定时器,这个函数需要输入一个以毫秒为单位的整数作为参数来表明设定的时间,它返回的整型值代表这个定时器。当定时器溢出时(即定时时间到达)就可以在 timerEvent() 函数中获取该定时器的编号来进行相关操作
  • QTimer类来实现一个定时器,它提供了更高层次的编程接口,如:可以使用信号和槽,还可以设置只运行一次的定时器

5.1 QTimerEvent类 

代码示例:在UI界面上放置两个Label,一个1秒数字累加一次,一个2秒数字累加一次

在"widget.h"头文件中声明timerEvent()函数,并定义两个整型变量

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTimerEvent>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();//重写定时器事件void timerEvent(QTimerEvent* event);
private:Ui::Widget *ui;int timerId1 = 0;int timerId2 = 0;
};
#endif // WIDGET_H

在"widget.cpp"文件中重写timerEvent()函数

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//启动定时器timerId1 = startTimer(1000);timerId2 = startTimer(2000);
}Widget::~Widget()
{delete ui;
}void Widget::timerEvent(QTimerEvent *event)
{if(event->timerId() == timerId1) {static int count1 = 1;ui->label->setText(QString::number(count1++));}if(event->timerId() == timerId2) {static int count2 = 1;ui->label_2->setText(QString::number(count2++));}
}

5.2 QTimer类

在UI界面放置一个Label标签,两个按钮,分别是"开始"和"停止",当点击"开始"按钮时,开始每隔1秒计数一次,点击"停止"按钮时,暂停计数

#include "widget.h"
#include "ui_widget.h"
#include <QTimer>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QTimer* timer = new QTimer(this);connect(ui->pushButtonStart, &QPushButton::clicked, [=]() {timer->start(1000);});connect(timer, &QTimer::timeout, [=](){static int num = 1;ui->label->setText(QString::number(num++));});connect(ui->pushButtonStop, &QPushButton::clicked, [=](){timer->stop();});
}Widget::~Widget()
{delete ui;
}

5.3 获取系统日期及时间

在Qt中,获取系统的日期及实时时间可以通过QTimer类和QDateTime类。QDateTime类提供了字符串格式的时间。字符串形式的时间输出格式由toString()方法中的format参数列表决定

代码示例:获取系统日期及实时时间

设计UI界面文件;放置一个Label控件,用来显示日期及时间,放置两个按钮"开始"和"停止"

在"widget.h"头文件中声明更新时间的槽函数

在"widget.cpp"文件中实现对应功能

六、窗口移动和大小改变事件

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

代码示例

七、事件分发器

在Qt中,事件分发器(Event Dispatcher)是一个核心概念,用于处理GUI应用程序中的事件。事件分
发器负责将事件从一个对象传递到另一个对象,直到事件被处理或被取消。每个继承自QObject类或QObject类本身都可以在本类中重写bool event(QEvent *e)函数,来实现相关事件的捕获和拦截

事件分发器工作原理

在Qt中,发送的事件都是传给了QObject对象,更具体点是传给了QObject对象的event()函数。所有的事件都会进入到这个函数中,那么处理事件就要重写这个event()函数。event()函数本身不会去处理事件,而是根据事件类型(type值)调用不同的事件处理函数

事件分发器就是工作在应用程序向下分发事件的过程中,如下图:

在此过程中,事件分发器也可以做拦截操作。事件分发器主要是通过 bool event(QEvent *e) 函数来实现。其返回值为布尔类型,若为ture,代表拦截,不向下分发

代码示例

在"widget.h"头文件中声明鼠标按下事件和事件分发器

在"widget.cpp"文件中实现功能

#include "widget.h"
#include "ui_widget.h"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() << "鼠标左键被按下";
}bool Widget::event(QEvent *event)
{if(event->type() == QEvent::MouseButtonPress) {qDebug() << "事件分发器捕捉到鼠标按下事件";return true;//拦截}if(event->type() == QEvent::MouseButtonDblClick) {qDebug() << "事件分发器捕捉到鼠标双击事件";return true;//拦截}//其他事件交给父类处理(默认处理)return QWidget::event(event);
}

八、事件过滤器

在Qt中,一个对象可能经常要查看或拦截另外一个对象的事件,如对话框想要拦截按键事件,不让别的组件接收到,或者修改按键的默认值等

Qt创建了QEvent事件对象之后,会调用QObject的event()函数处理事件的分发。可以在event()函数中实现拦截的操作。由于event()函数是protected的,因此需要继承已有类。若组件很多,就需要重写很多个event()函数

这当然相当麻烦,更不用说重写event()函数还得小心一堆问题。好在Qt提供了另一种机制来达到这一目的 :事件过滤器

事件过滤器是在应用程序分发到event事件分发器之前,再做一次更高级的拦截。如下图示:

事件过滤器的一般使用步骤:

  1. 安装事件过滤器
  2. 重写事件过滤器函数:eventfilter()

代码示例

在"widget.h"中声明鼠标按下事件和事件分发器

在"widget.cpp"文件中实现鼠标点击事件和事件分发器

在"widget.h"头文件中声明事件过滤器函数

在"widget.cpp"文件中实现事件过滤器的两个步骤

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

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

相关文章

蓝桥杯刷题 前缀和与差分-[NewOJ P1819]推箱子(C++)

题目描述 在一个高度为H的箱子前方&#xff0c;有一个长和高为N的障碍物。 障碍物的每一列存在一个连续的缺口&#xff0c;第i列的缺口从第l各单位到第h个单位&#xff08;从底部由0开始数&#xff09;。 现在请你清理出一条高度为H的通道&#xff0c;使得箱子可以直接推出去。…

深度学习理论基础(二)深度神经网络DNN

目录 一、基础知识点Ⅰ 参数部分Ⅱ 模型部分 二、深度神经网络模型搭建1. 准备数据集2. 划分数据集3. 搭建模型4. 训练网络5. 测试网络6. 保存与导入模型 神经网络通过学习大量样本的输入与输出特征之间的关系&#xff0c;以拟合出输入与输出之间的方程&#xff0c;学习完成后&…

每日一题(leetcode31):下一个排列-思维

思路&#xff1a;从后往前找到第一个nums[i-1]>nums[i] 然后从后往前(len-1 -->i(包含))找到第一个大于nums[i-1]的数&#xff0c;与nums[i-1]交换&#xff0c;然后对下标区间为[i,len-1]的元素进行排序。 class Solution { public:void nextPermutation(vector<in…

[深度学习] 无人车环境准备

1. 安装过程基本遵循以下步骤 电脑端环境配置 - OriginBot智能机器人开源套件 需要注意以下两点&#xff1a; 1> 由于深度学习需要的包和镜像体积都比较大&#xff0c;所以虚拟机硬盘大小建议120GB 2> 虚拟机的网络适配器应该设置为桥接模式&#xff0c;如果使用NAT模…

vivado 使用网表插入调试探测流程

使用网表插入调试探测流程 在 Vivado 工具中插入调试核的过程以分层方式来演示 &#xff0c; 以应对多样化的 Vivado 用户组的不同需求 &#xff1a; • 最高层是根据选定调试的一组信号线来自动创建并配置 Integrated Logic Analyzer (ILA) 核的简单向导。 • 下一层是“…

File,IO流,递归详解

File类 介绍 java.io.File类是Java语言提供了用来描述文件和目录(文件夹)的 构造 方法 注意&#xff1a; 构造方法中通常用的是第一个方法文件和目录可以通过File封装成对象File封装的对象仅仅是一个路径名&#xff0c;它是可以存在的&#xff0c;也可以不存在 绝对路径…

【二分查找】Leetcode x 的平方根

题目解析 69. x 的平方根 这道题表面是没有顺序性&#xff0c;但是我们可以发现如果使用枚举策略&#xff0c;它是包含顺序性质的&#xff0c;因此我们将枚举算法改进成二分算法 算法讲解 我们让left指针指向1&#xff0c; right指针指向x 如果当前的mid计算出来的平方 &g…

什么是商家转账到零钱

商家转账到零钱是什么&#xff1f; 通过商家转账到零钱这个功能&#xff0c;如果我们系统需要对用户支付费用&#xff0c;比如发放佣金、提成、退款之类的&#xff0c;可以直接转账到用户的微信零钱。 【商家转账到零钱】是【企业付款到零钱】的升级版&#xff0c;2022年5月1…

怀俄明探空站数据解算PWV和Tm

1. Matlab 获取代码可关注公众号WZZHHH回复&#xff08;怀俄明探空站数据解算PWV和Tm&#xff09;&#xff0c;或者咸鱼关注&#xff1a;WZZHHH123 怀俄明探空站数据解算PWV和Tm&#xff1a; 有关 Matlab 获取代码可关注公众号WZZHHH回复&#xff08;怀俄明多线程下载&#…

语音助手背后的魔法:一文揭秘NLP在智能助手中的应用

自然语言处理&#xff08;NLP&#xff09;正逐渐渗透到我们生活的每一个角落。在今天的大盘点中&#xff0c;我们将深入探索NLP在实际生活场景中的多样化应用&#xff0c;以及它在各个案例中所展现出的强大能力。 NLP技术如今已成为智能生活的关键驱动力&#xff0c;它让机器能…

wordpress全站开发指南-面向开发者及深度用户(全中文实操)--php数组与基本循环

php数组与基本循环 <?php$myName"xixi";$namesarray(xixi1,xixi2,xixi3); ?> <p> Hi ,my name is <?php echo $myName; ?> </p> <p> Hi,my name is <?php echo $names[0] ?> </p> <p> Hi,my name is <?…

Open CASCADE学习|放样建模

在CAD软件中&#xff0c;Loft&#xff08;放样&#xff09;功能则是用于创建三维实体或曲面的重要工具。通过选取两个或多个横截面&#xff0c;并沿这些横截面进行放样&#xff0c;可以生成复杂的三维模型。在CAD放样功能的操作中&#xff0c;用户可以选择不同的选项来定制放样…

创新数智化全场景福利解决方案,打造极致员工体验

众所周知&#xff0c;企业面临两个市场&#xff0c;一个是前端的产品&#xff08;服务&#xff09;市场&#xff0c;面对的是客户&#xff0c;另一个便是后端市场&#xff0c;即愈来愈烈的人才市场。在风云变幻、人潮涌动的知识经济时代&#xff0c;员工已成为企业未来的竞争关…

Linux_进程通信_管道_system V共享内存_6

文章目录 一、进程通信分类二、管道1.什么是管道1.原理2.管道的特点 2.匿名管道3.命名管道1.创建命名管道文件 - mkfifo (命令)2.创建命名管道文件 - mkfifo (函数) 三、system V共享内存1.原理2.共享内存函数1.fotk2.shmget1.如何知道有哪些IPC资源 - ipcs &#xff08;命令&a…

河海大学-海洋学院2024年硕士研究生调剂通知

一、调剂专业及计划具体调剂专业及计划可参见河海大学研究生院官网《河海大学2024年硕士研究生调剂通知》和附件。 二、调剂报名与复试要求 1.报名条件&#xff1a;调剂原则见《河海大学202 4年硕士研究生调剂通知》&#xff0c;详细要求见中国研究生招生信息网“全国硕士研究…

Mysql密码修改问题

docker安装mysql&#xff0c;直接拉取镜像&#xff0c;挂载关键目录即可启动&#xff0c;默认3306端口。此时无法直接连接&#xff0c;需要配置密码。docker进入mysql容器中 docker exec -it mysql bash #mysq是容器名称&#xff0c;也可以用容器id通过修改mysql的配置进行免密…

Unity类银河恶魔城学习记录12-7-1 p129 Craft UI - part 1源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI_CraftList.cs using System.Collections; using System.Collections.Gen…

Vue基础知识:Vue路由——重定向,以及?(可选符)的使用

当网页打开时&#xff0c;url默认是/路径&#xff08;根路径&#xff09;&#xff0c;未匹配到组件时&#xff0c;会出现空白&#xff0c;为了解决这个问题 就要利用重定向 重定向&#xff1a;匹配path后&#xff0c;强制跳转path路径 重定向的语法&#xff1a; {path:匹配…

【Linux】使用cloudreve搭建个人网盘并传输文件

Cloudreve 是一个开源的个人网盘系统&#xff0c;能够帮助用户搭建属于自己的私有云存储服务。它支持多种存储后端&#xff0c;包括本地存储、远程FTP/SFTP存储、以及云存储服务如阿里云OSS、腾讯云COS和Amazon S3等。Cloudreve具有友好的用户界面和丰富的功能&#xff0c;比如…

如何使用开源情报跟踪一个人?在线访问网站以及使用方法介绍

如何使用开源情报跟踪一个人&#xff1f;在线访问网站以及使用方法介绍。 开源情报&#xff08;OSINT&#xff09;是一门关于收集和分析公开可用信息的独特技艺&#xff0c;它致力于构建个人或团体的详尽档案。 这一过程中&#xff0c;信息搜集者会利用多元化的信息源&#xff…