【Qt】事件

news2024/11/28 17:59:35

目录

一、介绍

二、进入离开事件

三、鼠标事件

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_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    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.coloradmin.cn/o/1586897.html

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

相关文章

20 Games101 - 笔记 - 光场、颜色与感知

**20 ** 光场、颜色与感知 光场 眼睛成像 眼睛成像&#xff1a;我们看到这个三维世界&#xff0c;在眼睛里类似就是一幅二维的图。如果直接看到一幅记录了看到的光线信息的图&#xff0c;也能得到同样效果&#xff08;虚拟现实&#xff09;。 全光函数 全光函数可以描述…

基因组组装:Hifiasm 使用教程

简介 Hifiasm[1] 是一个快速的单倍型解析 de novo 组装软件&#xff0c;最初设计用于 PacBio HiFi 读取。其最新版本可以通过利用超长的 Oxford Nanopore 读取支持端粒到端粒的组装。Hifiasm 可以生成单样本端粒到端粒的组装&#xff0c;结合了 HiFi、超长和 Hi-C 读取&#xf…

【示例】MySQL-4类SQL语言-DDL-DML-DQL-DCL

前言 本文主要讲述MySQL中4中SQL语言的使用及各自特点。 SQL语言总共分四类&#xff1a;DDL、DML、DQL、DCL。 SQL-DDL | Data Definition Language 数据定义语言&#xff1a;用来定义/更改数据库对象&#xff08;数据库、表、字段&#xff09; 用途 | 操作数据库 # 查询所…

Linux开发--进程

经典五问&#xff1a; 1.什么是程序&#xff1f;什么是进程&#xff1f; 从是否运行进行判断: gcc xxx -o pro&#xff0c;磁盘中生成的pro文件&#xff0c;就是程序 进程是程序一次运行活动 程序是静态的概念&#xff0c;进程是动态的概念。 2.如何查看系统中的进程: 在l…

无重复字符串的最长子串

题目描述&#xff1a;给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串的长度。 第一次提交记录 class Solution:def lengthOfLongestSubstring(self, s: str) -> int:if not s:return 0lookup set()left res 0for right in range(len(s)):while s…

2024年人工智能路线图

今天分享的是人工智能专题系列深度研究报告&#xff1a;《人工智能专题&#xff1a;2024年人工智能路线图》。 秘书制定部门的人工智能战略优先事项和政策&#xff0c;并且是关键的对话者与私营部门、联邦机构、州官员&#xff0c;以及主要的国际同行。这部长在白宫人力资源委员…

MindSQL

文章目录 关于 MindSQL安装代码调用&#x1f4c1; 项目代码结构其它 关于 MindSQL MindSQL 是一个 Python RAG 库&#xff0c;旨在仅使用几行代码来简化用户与其数据库之间的交互。 MindSQL 与 PostgreSQL、MySQL、SQLite 等知名数据库无缝集成&#xff0c;还通过扩展接口将其…

基于ssm的前后端分离鲜花销售系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本鲜花销售系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&am…

async+await——用法——基础积累

对于asyncawait&#xff0c;我一直都不太会用。。。。 今天记录一下asyncawait的实际用法&#xff1a; 下面是一个实际的使用场景&#xff1a; 上面的代码如下&#xff1a; async fnConfirmCR(){let type this.crType;let crId this.crId;if(typeof crId object){let ne…

SXSSFWorkbook实现分页查询导出

继上一篇性能爆炸&#xff01;SXSSFWorkbook原文件上追加写入&分页导出_sxssfworkbook 模板写入-CSDN博客 那篇其实还没有完全爆炸&#xff0c;但为啥不删除那一篇呢&#xff0c;因为那篇也算是一种思路。这篇文章是属于另外一种思路的玩法。上一篇是读取一个已有的excel再…

智能合约:未来数字经济的基石

智能合约是一种自动执行交易的计算机协议&#xff0c;它以代码形式规定了交易双方的权利和义务&#xff0c;具有高度的可靠性和安全性。随着数字经济的发展&#xff0c;智能合约的重要性日益凸显&#xff0c;将成为未来数字经济的基石。 首先&#xff0c;智能合约在金融领域的应…

深度学习Vue框架生命周期(三)

一.什么是生命周期&#xff1f; 在vue中&#xff0c;生命周期就是vue实例程序从创建到销毁的这个过程&#xff0c;在生命周期中&#xff0c;不同阶段我们可以做不同的事情。vue的生命周期是创建阶段、挂载阶段、更新阶段、销毁阶段 二.什么是钩子函数&#xff1f; 钩子函数就是…

数学杂谈之三:数学思想方法

数学杂谈之三&#xff1a;数学思想方法 数学杂谈之一&#xff1a;数学的形态 https://blog.csdn.net/cnds123/article/details/137437208 数学杂谈之二&#xff1a;数学中的概念和理解 https://blog.csdn.net/cnds123/article/details/137500537 数学思维、数学思想和数学方法…

1200/天,长期兼职贵么?

今天收到一个客户询盘&#xff0c;问公司长期招聘一个兼职程序员&#xff0c;包月的这种。问我多少钱一个月&#xff0c;在这种需求未明确的情况下&#xff0c;单纯的问价格其实意义不大的&#xff0c;只要报价不在客户心理预期范围内基本没戏的。 关于定价 关于程序员价格的定…

【进阶六】Python实现SDVRPTW常见求解算法——差分进化算法(DE)

基于python语言&#xff0c;采用经典差分进化算法&#xff08;DE&#xff09;对 带硬时间窗的需求拆分车辆路径规划问题&#xff08;SDVRPTW&#xff09; 进行求解。 目录 往期优质资源1. 适用场景2. 代码调整2.1 需求拆分2.2 需求拆分后的服务时长取值问题 3. 求解结果4. 代码…

【spring】@Profile注解学习

Profile介绍 在Spring框架中&#xff0c;Profile注解用于根据特定的配置文件来有条件地激活或禁用Bean的定义。这在开发和测试过程中非常有用&#xff0c;因为它允许你为不同的环境&#xff08;如开发、测试、生产&#xff09;定义不同的配置。 Profile不仅可以标注在方法上&…

arm内核驱动-中断

先介绍个东西 ctags 这个工具可以像keil一样在工程里查找跳转&#xff0c;帮我们找到我们想要的东西。 安装教程可以找到&#xff0c;这里只讲怎么用。 在工程目录&#xff08;包含所有你会用到的头文件等&#xff09;下&#xff0c;先加载这个命令&#xff0c;可能要等待…

第十五讲:C语言内存函数

目录 1、C语言内存函数 1.1、memcpy函数的使用和模拟 1.2、memmove函数的使用和模拟 1.3、memset函数的使用 1.4、memcmp函数的使用 1、C语言内存函数 注意&#xff1a;下面这些函数的使用要包含头文件&#xff1a;string.h 1.1、memcpy函数的使用和模拟 函数声明为&am…

2024年第十七届 认证杯 网络挑战赛 (C题)| 云中的海盐 | 辐射传输方程 Stefan-Boltzmann分析 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 让我们来看看认证杯 网络挑战赛 (C题&#xff09;&#xff01…

PTA qls学画图

这一天qls在学校综合楼等电梯的时候看到了电梯数字的样子&#xff0c;突然觉得这样写数字特别有趣&#xff0c;于是自己想用程序跑出来。由于正常大小输出数字太小了&#xff0c;qls决定加大难度&#xff0c;他想画出不同大小的数字&#xff0c;你能帮他解决这个问题吗&#xf…