Qt系统相关——事件

news2024/9/23 6:18:50

文章目录

    • 事件和信号槽的关系
    • 事件处理
    • 鼠标事件
      • 鼠标进入和离开
      • 鼠标点击获取位置
      • 鼠标释放
      • 鼠标双击
      • 鼠标移动
      • 鼠标滚轮
    • 键盘事件
    • 定时器事件
    • 窗口移动和窗口改变

事件和信号槽的关系

Qt信号槽机制: 用户进行的操作就可能产生信号,可以给某个信号指定槽函数,当信号触发的时候,就能够执行到对应的槽函数。

对于事件,和信号槽类似,用户进行的各种操作,也会产生事件,可以给事件关联处理函数,当事件触发的时候,就能够执行到对应的代码。

事件本身是由操作系统提供的机制,Qt将操作系统事件机制进行封装。

但是事件对应的代码编写起来不方便,Qt对事件机制又继续了进一步封装,就得到了信号槽。

事件是信号槽的底层机制

大部分情况都是采用信号槽,但对于有些行为,Qt没有提供对应的信号,此时就需要重写事件处理函数,来手动处理事件的响应逻辑了。

事件机制,灵活度更高。

常见Qt事件:

image-20240922090528528

常见事件描述:

事件名称描述
鼠标事件鼠标左键、鼠标右键、鼠标滚轮、鼠标的移动、鼠标按键的按下和松开
键盘事件按键类型、按键按下、按键松开
定时器事件定时时间到达
进入离开事件鼠标的进入和离开
滚轮事件鼠标滚轮滚动
绘屏事件重绘屏幕的某些部分
显示隐藏事件窗口的显示和隐藏
移动事件窗口位置的变化
窗口事件是否为当前窗口
大小改变事件窗口大小改变
焦点事件键盘焦点移动
拖拽事件用鼠标进行拖拽

事件处理

事件处理就是让一段代码和某个事件关联起来,当事件触发的时候,就能指定到这段代码。

之前信号槽是通过connect来完成上述关联的;

对于事件,让当前的类,重写某个事件处理函数。

属于多态机制,创建子类,继承Qt自己的类,然后重新父类的事件处理函数。

鼠标事件

鼠标进入和离开

处理一下鼠标的进入和离开事件

image-20240922092214568

ui界面:

image-20240922093513461

创建QLabel的子类,然后重写enterEventleaveEvent

image-20240922094435747

label.h

#ifndef LABEL_H
#define LABEL_H

#include <QWidget>
#include<QLabel>
class Label : public QLabel
{
    Q_OBJECT
public:
    Label(QWidget* parent);
    
    void enterEvent(QEvent* event);
    void leaveEvent(QEvent* event);
};

#endif // LABEL_H

label.cpp

#include "label.h"
#include<QDebug>
Label::Label(QWidget* parent)
    : QLabel(parent)
{
    
}

void Label::enterEvent(QEvent *event)
{
    (void)event;
    qDebug() << "enterEvent";
}

void Label::leaveEvent(QEvent *event)
{
    (void)event;
    qDebug() << "leaveEvent";    
}

此时重写完毕之后,只是对于Label,而界面是的是QLabel

要确保界面上的label是我们自定义的实例,才会执行到这两个函数。

image-20240922095020397

GIF 2024-9-22 9-51-09

鼠标点击获取位置

image-20240922100213101

label.cpp

#include "label.h"
#include<QDebug>
#include<QMouseEvent>
Label::Label(QWidget* parent)
    :QLabel(parent)
{}

void Label::mousePressEvent(QMouseEvent *event)
{
    //当前控件左上角为原点
    qDebug() << event->x() << "," << event->y();
    //屏幕左上角为原点
    qDebug() << event->globalX() << "," << event->globalY();
}

GIF 2024-9-22 10-11-31

这个函数可以触发鼠标的各种按键,例如左键、右键、滚轮等

#include "label.h"
#include<QDebug>
#include<QMouseEvent>
Label::Label(QWidget* parent)
   :QLabel(parent)
{}

void Label::mousePressEvent(QMouseEvent *event)
{
   if(event->button() == Qt::LeftButton)
   {
       qDebug() << "左键触发"; 
   }
   else if(event->button() == Qt::RightButton)
   {
       qDebug() << "右键触发";	
   }
   //当前控件左上角为原点
   qDebug() << event->x() << "," << event->y();
   //屏幕左上角为原点
   qDebug() << event->globalX() << "," << event->globalY();
}

image-20240922114302874

鼠标释放

基于上面的代码,重写鼠标释放函数

image-20240922114904755

void Label::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        qDebug() << "左键释放";
    }
    else if(event->button() == Qt::RightButton)
    {
        qDebug() << "右键释放";
    }
}

一次clicked,相当于鼠标一次按下事件+一次释放事件

鼠标双击

重写双击虚函数

image-20240922115103366

void Label::mouseDoubleClickEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        qDebug() << "左键双击";
    }
    else if(event->button() == Qt::RightButton)
    {
        qDebug() << "右键双击";
    }
}

GIF 2024-9-22 11-55-06

这里双击的时候,也会触发单击的事件,这就又有可能导致意外的情况

鼠标移动

上面都是在Label控件里面进行活动,也可以直接放到Widget里面来完成。

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 mouseMoveEvent(QMouseEvent* event);

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QMouseEvent>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    qDebug() << event->x() << event->y();
}

上面的代码,不会直接移动的时候捕获位置,因为鼠标经常移动,稍微移动一下,就会产生大量的鼠标移动事件。

在捕获事件的时候,如果这里逻辑很复杂,就会导致程序特别卡顿。

为了保证程序流畅性,默认不会对鼠标移动进行追踪,鼠标移动的时候,不会调用mouseMoveEvent,除非显式告诉Qt

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setMouseTracking(true);
}

鼠标滚轮

通过wheelEvent

image-20240922144016520

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QMouseEvent>
#include<QWheelEvent>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    total = 0;
}

Widget::~Widget()
{
    delete ui;
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    qDebug() << event->x() << event->y();
}

void Widget::wheelEvent(QWheelEvent *event)
{
    total += event->delta();
    qDebug() << total;
}

键盘事件

QShortCut定义一个快捷键,然后搭配QKeySequence这个类,指定当前按键是什么按键序列。如果按下这个键,就触发actived信号。这是信号槽机制封装过的,获取键盘按键的快捷方式。

也可以通过事件获取到当前用户键盘按下的情况。

重写一个父类函数,keyPressEvent

image-20240922145245623

单个按键:

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QKeyEvent>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::keyPressEvent(QKeyEvent *event)
{
    qDebug() << event->key();
}

组合按键:

image-20240922154253465

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QKeyEvent>
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 && event->modifiers() == Qt::ControlModifier)
    {
        qDebug() << "alt + A";
    }
}

定时器事件

可以使用QTimer这个类来完成定时器这个功能。

QTimer背后是QTimerEvent定时器事件来进行支撑;

QObject提供了timerevent这个函数:

  • startTimer启动定时器
  • killTimer关闭定时器

image-20240922155257245

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 timerEvent(QTimerEvent *event);
private:
    Ui::Widget *ui;
    int timerId;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //开启定时器事件
    //startTimer由QObject提供
    //Widget继承QWidget
    //QWidget继承QObject

    //返回一个整数,定时器身份标识
    timerId = this->startTimer(1000);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::timerEvent(QTimerEvent *event)
{
    //一个程序存在多个定时器, 每个定时器都会触发这个函数
    //需要判断,这次触发是否是想要的定时器触发的
    if(event->timerId() != this->timerId)
    {
        return;
    }
    int value = ui->lcdNumber->intValue();
    if(value <= 0)
    {
        this->killTimer(this->timerId);
        return;
    }
    value -= 1;
    ui->lcdNumber->display(value);
}

窗口移动和窗口改变

  • moveEvent窗口移动时触发的事件image-20240922155900630
  • resizeEvent窗口大小改变时触发的事件
    image-20240922160017780
#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
#include<QMoveEvent>
#include<QResizeEvent>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::moveEvent(QMoveEvent *event)
{
    qDebug() << event->pos();
}

void Widget::resizeEvent(QResizeEvent *event)
{
    qDebug() << event->size();
}

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

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

相关文章

Effective Java 学习笔记 如何为方法编写文档

目录 方法的文档注解设计的原则 Javadoc常用的文档注释 一些注意细节 通过Javadoc命令生成h5页面 这是第8章Java方法的最后一部分&#xff0c;聚焦为导出的API编写文档注释。 如果要想使得API真正可用&#xff0c;配套的文档是必须的。Java提供了Javadoc这个文档生成工具&…

Renesas R7FA8D1BH (Cortex®-M85)的 General PWM的应用实践

目录 概述 1 General PWM介绍 1.1 特性 1.2 定时器选择注意点 2 时钟配置 3 应用案例 3.1 基本定时器应用 3.2 定时器回调函数案例 3.3 输入捕捉功能案例 3.4 更新周期案例 3.5 更新占空比案例 3.6 单次触发脉冲案例 4 测试 4.1 代码介绍 4.2 验证 概述 本文主…

基于SpringBoot+Vue+MySQL的特色旅游网站系统

系统展示 用户前台界面 管理员后台界面 系统背景 随着旅游业的蓬勃发展&#xff0c;人们对旅游体验的需求日益多样化与个性化。传统的旅游信息查询与预订方式已难以满足现代游客的需求。因此&#xff0c;我们开发了这款基于SpringBootVueMySQL的特色旅游网站系统。该系统旨在通…

HTML实现的简单网站首页模板

这个是简单的网站首页模板&#xff0c;用于学习或者参考 实现代码: <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"&…

移动硬盘‘需格式化‘困境:原因剖析、恢复策略与预防之道

困境直击&#xff1a;移动硬盘为何需格式化才能访问&#xff1f; 在数字化时代&#xff0c;移动硬盘作为数据存储与传输的重要工具&#xff0c;其稳定性与可靠性直接关系到用户数据的安全。然而&#xff0c;不少用户在使用过程中遭遇了“移动硬盘需要格式化才能打开”的尴尬境…

Qt_对话框QDialog的介绍

目录 1、新建项目对话框 2、非模态对话框 3、模态对话框 4、自定义对话框 5、Qt内置对话框 5.1 消息对话框QMessageBox 5.2 颜色对话框QColorDialog 5.3 文件对话框QFileDialog 5.4 字体对话框QFontDialog 5.5 输入对话框QInputDialog 结语 前言: 在Qt中&…

布草洗涤必备4张表-———未来之窗行业应用跨平台架构

一、洗涤厂客户月度报表 二、大酒店楼层布草月度统计报表 三、职员月度报表 四、司机当日统计报表 五、阿雪技术观 拥抱开源与共享&#xff0c;见证科技进步奇迹&#xff0c;畅享人类幸福时光&#xff01; 让我们积极投身于技术共享的浪潮中&#xff0c;不仅仅是作为受益者&a…

【软件测试】Bug 篇

哈喽&#xff0c;哈喽&#xff0c;大家好~ 我是你们的老朋友&#xff1a;保护小周ღ 今天给大家带来的是 【软件测试】Bug 篇&#xff0c;首先了解, 什么是Bug, 如何定义一个Bug, 如何描述一个 Bug, Bug的级别, 和 Bug 的生命周期, 以及测试人员跟开发人员产生争执如何处理,…

最佳植树距离 - 华为OD统一考试(E卷)

2024华为OD机试&#xff08;C卷D卷E卷&#xff09;最新题库【超值优惠】Java/Python/C合集 题目描述 按照环保公司要求&#xff0c;小明需要在沙化严重的地区进行植树防沙工作&#xff0c;初步目标是种植一条直线的树带。由于有些区域目前不适合种植树木&#xff0c;所以只能在…

橙子质量检测系统源码分享

橙子质量检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

【报告阅读】chatgpt-o1 技术报告阅读 | 新的迭代开始了~

OpenAI o1是通过强化学习去进行复杂推理&#xff0c;在它回答之前&#xff0c;他会经过复杂的内部思维链的思考。 经过强化训练的o1多强 1 表现 在美国数学奥林匹克预选赛中名列前500名的学生中&#xff0c;o1排89名 在物理、生物、化学问题的基准测试中超过人类博士水平 其…

stm32单片机个人学习笔记7(TIM定时中断)

前言 本篇文章属于stm32单片机&#xff08;以下简称单片机&#xff09;的学习笔记&#xff0c;来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记&#xff0c;只能做参考&#xff0c;细节方面建议观看视频&#xff0c;肯定受益匪浅。 STM32入门教程-2023版 细…

Python可迭代对象(1)---从C++开发者学习python日记

目录 1。什么是可迭代对象&#xff1f; 2。列表(list) 列表的创建 列表基本操作 以上全部代码的总运行结果 列表脚本操作符 列表常用的方法和函数 列表推导式 ​编辑列表的嵌套 以上全部代码的总运行结果 复习列表内容 3。元组(tuple) 元组的基本运算 元组的方法 …

SFUD库移植

1.源码 GitHub - armink/SFUD: An using JEDECs SFDP standard serial (SPI) flash universal driver library | 一款使用 JEDEC SFDP 标准的串行 (SPI) Flash 通用驱动库 2.介绍 这个通用驱动库,实际就是帮你封装好了读写spiflash的函数, 我们只需要对接以下底层,就可以轻松…

快速了解使用路由器

插槽的使用和用法&#xff1a;slot 为什么要使用插槽&#xff1a; 在Vue.js等前端框架中 在Vue.js等前端框架中&#xff0c;插槽&#xff08;Slot&#xff09;是一种强大的工具&#xff0c;允许开发者在组件之间动态地传递和呈现内容。使用插槽的主要原因包括&#xff1a; …

【LTW】Domain General Face Forgery Detection by Learning to Weight

文章目录 Domain General Face Forgery Detection by Learning to Weightkey points方法LTW元分割策略学习过程损失函数实验评价结果消融实验总结Domain General Face Forgery Detection by Learning to Weight 会议:AAAI-21 作者: code: https://github.com/skJack/LTW 上…

用uniapp 及socket.io做一个简单聊天 升级 9

比这之前优化了以下功能 上线通知 群聊里适时显示在线人数 约请好友 通过好友通过socket 相应端自动变化 PC端可以拉取摄象头拍照 PC端可以录音发送 拉起摄象头发送录象 <template><view class""><scroll-view scroll-y"true" class&…

2024 离线ASR和TTS推荐与示例

2024 离线ASR和TTS推荐 文章目录 2024 离线ASR和TTS推荐一、前言二、安装与使用1、EdgeTTS的安装和使用&#xff08;1&#xff09;Edge TTS介绍与效果试听&#xff08;2&#xff09;Edge TTS安装&#xff08;3&#xff09;Edge TTS查看支持的音色&#xff08;4&#xff09;Edge…

16【Protues51单片机仿真】智能洗衣机倒计时系统

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 用直流电机转动模拟洗衣机。要求 有弱洗、普通洗、强洗三种模式&#xff0c;可通过按键选择。可以设置洗衣时长&#xff0c;通关按键选择15、30、45、60、90分钟。时间到蜂鸣器报警提示。LCD 显示…

MySQL:事务的ACID特性隔离级别脏读/不可重复读/幻读/Next-Key锁——场景复现

目录 1、什么是事务 2、 事务的ACID特性 2.1 事务的隔离性 3、为什么要使用事务&#xff1f; 4、查看支持事务的存储引擎 5、使用事务 5.1 控制事务 5.1.1 开启事务 5.1.2 关闭事务 5.2 开始一个事务&#xff0c;执行修改后回滚 5.3 开始一个事务&#xff0c;执行修…