【QT】Qt事件

news2024/9/22 4:01:03

目录

前置知识

事件概念

常见的事件描述

进入和离开事件

代码示例: 

鼠标事件

鼠标点击事件

鼠标释放事件 

鼠标双击事件

鼠标滚轮动作

键盘事件

定时器事件

开启定时器事件

窗口相关事件

窗口移动触发事件 

窗口大小改变时触发的事件

扩展


前置知识

        在前面的介绍中,我们知道信号槽就是:用户进行的各种操作,就可能会产生出信号,可以给某个信号指定槽函数,当信号触发时,就能够自动的执行对应的槽函数。

        这里的事件也是类似的,用户进行的各种操作,也会产生事件,程序员同样可以给事件关联上处理函数(处理的逻辑),当事件触发的时候,就能够执行到对应的代码。

        事件本身是操作系统提供的机制,Qt也同样把操作系统的事件机制进行了封装,拿到了Qt中,但是由于事件对应的代码编写起来不是很方便,Qt对于事件机制又进行了进一步的封装,就得到了信号槽。

        也就是说,信号槽就是对于事件的进一步封装,事件是信号槽的底层机制

        实际上Qt开发过程中,绝大部分和用户之间进行的交互都是通过“信号槽”,来完成的,有些特殊情况下,信号槽不一定能搞定(某个用户的动作行为,Qt中没有提供对应的信号……)此时就需要通过重写事件处理函数的形式,来手动处理事件的响应逻辑。

事件概念

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

常见的事件描述

事件名称描述
⿏标事件
⿏标左键、⿏标右键、⿏标滚轮,⿏标的移动,⿏标按键的按下和松开
键盘事件
按键类型、按键按下、按键松开
定时器事件
定时时间到达
进⼊离开事件
⿏标的进⼊和离开
滚轮事件
⿏标滚轮滚动
绘屏事件
重绘屏幕的某些部分
显⽰隐藏事件
窗⼝的显⽰和隐藏
移动事件
窗⼝位置的变化
窗⼝事件
是否为当前窗⼝
⼤⼩改变事件
窗⼝⼤⼩改变
焦点事件
键盘焦点移动
拖拽事件
⽤⿏标进⾏拖拽

进入和离开事件

这里需要创建QLabel的子类,重写enterEvent和leaveEvent。

注意:要想重写父类的函数,就需要确保这里写的函数名字和函数的参数列表一致(形参名无所谓)

这里要注意,我们通过图形化创建的label是QLabel类的,不是我们创建的子类的实例,我们可以将他提升为Label,也就是我们创建的子类。

此时在看这个控件的类型,可以发现已经变为Label

代码示例: 

label.h

#ifndef LABEL_H
#define LABEL_H
#include <QLabel>
#include <QWidget>

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"<<endl;
}

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

效果如下:

鼠标事件

鼠标点击事件

mousePressEvent()用法示例:

void Label::mousePressEvent(QMouseEvent *ev)
{
    //当前event对象就包含了鼠标点击位置的坐标
    qDebug()<<ev->x()<<','<<ev->y();

    qDebug()<<ev->globalX()<<','<<ev->globalY();
}

        这个事件处理的是鼠标点击后,显示鼠标点击位置的坐标, 如下所示,返回两个坐标,但是这两个坐标并不相同,因为 ev->globalX()和ev->globalY()返回的是以屏幕左上角为原点的坐标,x()和y()是以label标签左上角为原点的坐标。

         这里的mousePressEvent不仅是左键点击触发,右键和滚轮点击也可触发,有的鼠标还带有前进后退侧键也是可以触发的。 

         我们有时也要区分用户按了什么按钮,因此可以加上一层判断,如下:

    if(ev->button()==Qt::LeftButton)
    {
        qDebug()<<"按下左键";
    }
    else if(ev->button()==Qt::RightButton)
    {
        qDebug()<<"按下右键";
    }

鼠标释放事件 

mouseReleaseEvent()用法如下:

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

鼠标双击事件

如果设置了鼠标单击事件,需要注意逻辑处理,只有第二次按下的时候,才能够识别是双击。双击的同时可能会触发单击事件。

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

        上述重写鼠标事件的操作,都是在自定义的label中完成的,此时鼠标只有在label范围进行动作,才能捕获到,也可以把这些操作直接放到Widget(QWidget子类)来完成,这样的话,鼠标在整个窗口中进行的各种动作都能获取到了。

        其中鼠标移动不同于鼠标按下,随便移动下鼠标,就会产生大量的鼠标移动事件,当进行捕获事件的时候,尤其是在进行一些复杂逻辑的时候,程序负担就很重,就很容易产生卡顿的情况,

        Qt为了保证程序的流畅性,默认情况下不会对鼠标移动进行追踪。也就是说鼠标移动的时候,不会调用mouseMoveEvent,除非显式告诉qt追踪鼠标位置。做法如下:

    this->setMouseTracking(true);

鼠标滚轮动作

通过dalta()方法可以或者滚轮滚动的距离。

void Widget::wheelEvent(QWheelEvent *ev)
{
    qDebug()<<ev->delta();
}

键盘事件

要想获取到用户的键盘按键,QShortCut这是信号槽机制封装过,获取键盘按键的方式。站在底层的角度,也可以通过事件获取到当前用户键盘按下的情况。

void Widget::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_A)
    {
        qDebug()<<"按下了 A 键";
    }
}

上述只是获取单个按键,有时候我们需要获取组合键之类的操作,如下 ctrl + a

void Widget::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_A && event->modifiers() == Qt::ControlModifier)
    {
        qDebug()<<"按下了 ctrl + A 键";
    }
}

定时器事件

QTimer实现了定时器的功能,在QTimer背后是QTimerEvent定时器事件进行支撑的,QObject提供了一个timerEvent这个函数,startTimer 启动定时器,killTimer关闭定时器。

开启定时器事件

int timerId = this->startTimer(1000);

此处的timerId类似于Linux课堂上谈到的“文件描述符”,起到了身份标识的效果。

使用示例:

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

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

void Widget::timerEvent(QTimerEvent *event)
{
    //如果一个程序中存在多个定时器(startTimer 创建的定时器,此时每个定时器都会触发timerEvent函数)
    //先判断以下这次触发是否是想要的定时器触发的
    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);
}



使用timerEvent比QTimer 还是要更复杂一点,手动管理timerId,还需要区分这次调用是哪个timer引起的。

窗口相关事件

窗口移动触发事件 

moveEvent();

const QPoint & oldpos() const;

const QPoint & pos() const;

示例: 

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


窗口大小改变时触发的事件

resizeEvent();

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

扩展

事件分发/事件过滤 属于Qt事件机制背后的一些逻辑,事件分发就是重写event函数,直接获取所有事件,这个后续进行介绍。

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

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

相关文章

知识改变命运 第七集(下):Java中数组的定义与使用

4. 数组练习 4.1 数组转字符串 import java.util.Arrays int[] arr {1,2,3,4,5,6}; String newArr Arrays.toString(arr); System.out.println(newArr); // 执行结果 [1, 2, 3, 4, 5, 6]使用这个方法后续打印数组就更方便一些. Java 中提供了 java.util.Arrays 包, 其中包含…

SwiftUI 截图(snapshot)视频画面的极简方法

功能需求 在 万物皆可截图:SwiftUI 中任意视图(包括List和ScrollView)截图的通用实现 这篇博文中,我们实现了在 SwiftUI 中截图几乎任何视图的功能,不幸的是它对视频截图却无能为力。不过别着急,我们还有妙招。 在上面的演示图片中,我们在 SwiftUI 中可以随心所欲的截图…

【ZooKeeper学习笔记】

1. ZooKeeper基本概念 Zookeeper官网&#xff1a;https://zookeeper.apache.org/index.html Zookeeper是Apache Hadoop项目中的一个子项目&#xff0c;是一个树形目录服务Zookeeper翻译过来就是动物园管理员&#xff0c;用来管理Hadoop&#xff08;大象&#xff09;、Hive&…

浪潮信息F-OCC算法夺冠,自动驾驶感知技术再创新高

浪潮信息&#xff0c;作为行业领先的AI技术提供商&#xff0c;其AI团队在近期举办的全球权威CVPR 2024自动驾驶国际挑战赛(Autonomous Grand Challenge)中大放异彩&#xff0c;凭借“F-OCC”算法模型以48.9%的卓越成绩&#xff0c;一举夺得占据栅格和运动估计(Occupancy & …

前端Vue组件化实践:打造仿京东天猫商品属性选择器组件

在前端开发领域&#xff0c;随着业务需求的日益复杂和技术的不断进步&#xff0c;传统的整体式应用开发模式已逐渐显得捉襟见肘。面对日益庞大的系统&#xff0c;每次微小的功能修改或增加都可能导致整个逻辑结构的重构&#xff0c;形成牵一发而动全身的困境。为了解决这一问题…

基于Node.js将个人网站部署到ECS

基于Node.js将个人网站部署到云端ECS 一、如何购买ECS以及如何使用学生认证优惠&#xff1f;1.进入阿里云网站&#xff0c;进行学生认证2.购买学生优惠&#xff0c;免费试用一个月3.重置个人密码 二、服务器的配置以及与宝塔面板的链接1.个人电脑打开终端&#xff08;winR->…

探索性数据分析:使用Python与Pandas库实现数据洞察

探索性数据分析&#xff1a;使用Python与Pandas库实现数据洞察 引言 在当今数据驱动的时代&#xff0c;数据分析已成为决策制定、策略规划和业务优化的关键环节。无论是商业智能、金融分析还是市场研究&#xff0c;数据分析都扮演着至关重要的角色。Pandas库作为Python生态系统…

一文SpringCloud

Springcloud 什么是Springcloud&#xff1f; 官网&#xff1a;Spring Cloud Data Flow Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发&#xff0c;如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控…

Flat Ads:金融APP海外广告投放素材的优化指南

在当今全球化的数字营销环境中,金融APP的海外营销推广已成为众多金融机构与开发者最为关注的环节之一。面对不同地域、文化及用户习惯的挑战,如何优化广告素材,以吸引目标受众的注意并促成有效转化,成为了广告主们亟待解决的问题。 作为领先的全球化营销推广平台,Flat Ads凭借…

树莓派PICO使用INA226测量电流和总线电压(3)

上一篇文章我们讲了如何测试电流&#xff0c;但是INA226有一个非常典型的问题&#xff0c;那就是误差比较大&#xff0c;因为采样电阻非常小&#xff0c;我的开发板用的是100mΩ的采样电阻&#xff0c;在设定中我也用的是这个采样电阻值&#xff0c;但事实上&#xff0c;测试得…

文件内容查阅

cat concatenate files and print on the standard output Linux中一个最简单的且最常用的命令是cat命令。其功能是在终端设备上显示文件内容。 cat命令-n选项用于显示行号。 tac concatenate and print files in reverse tac命令的功能是用于反向显示文件内容&#xff0c;即…

【Qt 基础】绘图

画笔 QPen pen; pen.setWidth(3); // 线条宽度 pen.setColor(Qt::red);// 画笔颜色 pen.setStyle(Qt::DashLine);// 线条样式 pen.setCapStyle(Qt::RoundCap);// 线端样式 pen.setJoinStyle(Qt::BevelJoin);// 连接样式 painter.setPen(pen);线条 线端 连接 画刷 QBrush bru…

css设置弹性flex后,如果设置100vh高度不撑满的原因

问题 父元素设置height为100%&#xff0c;有两个子元素&#xff0c;第一个设置height:100vh&#xff0c;第二个设置flex:1&#xff0c;此时第一个高度无法撑满盒子 原因解决方式 当父元素设置display为flex,第一个div设置高度64px,剩一个div设置高度为flex&#xff1a;1,这时…

数据处理-Matplotlib 绘图展示

文章目录 1. Matplotlib 简介2. 安装3. Matplotlib Pyplot4. 绘制图表1. 折线图2. 散点图3. 柱状图4. 饼图5. 直方图 5. 中文显示 1. Matplotlib 简介 Matplotlib 是 Python 的绘图库&#xff0c;它能让使用者很轻松地将数据图形化&#xff0c;并且提供多样化的输出格式。 Ma…

Qt项目中添加自定义文件夹,进行整理归类

Qt项目中添加文件夹进行归类 1、在windows的工程目录下创建一个文件夹&#xff0c;如widgets 2、将.h 、.cpp、.ui文件拷贝到windows该文件夹widgets 3、在qt工程中&#xff0c;根目录右键&#xff0c;选择添加现有文件&#xff0c;批量选择 .h 、.cpp、.ui文件之后&#xf…

初识影刀:EXCEL根据部门筛选低值易耗品

第一次知道这个办公自动化的软件还是在招聘网站上&#xff0c;了解之后发现对于办公中重复性的工作还是挺有帮助的&#xff0c;特别是那些操作非EXCEL的重复性工作&#xff0c;当然用在EXCEL上更加方便&#xff0c;有些操作比写VBA便捷。 下面就是一个了解基本操作后&#xff…

开发总结 - H5/web C端评论区开发逻辑

1. 背景 平时做的系统都是偏公司业务的系统&#xff0c;这次开发了一个用户评论的功能&#xff0c;同时开发了web版和H5版本的&#xff0c;因为没有做过这种C端的常用的功能&#xff0c;所以记录一下此次的开发&#xff0c;从参考友商设计到独立思考业务之间的区别再到实际开发…

everything搜索不到任何文件-设置

版本&#xff1a; V1.4.1.1024 (x64) 问题&#xff1a;搜索不到任何文件 click:[工具]->[选项]->下图所示 将本地磁盘都选中包含

2024 辽宁省大学数学建模竞赛B 题 钢铁产品质量优化完整思路 代码 结果分享(仅供学习)

冷轧带钢是钢铁企业的高附加值产品,其产品质量稳定性对于钢铁企业的经济效益具有非常重要的影响。在实际生产中&#xff0c;冷连轧之后的带钢需要经过连续退火处理来消除因冷轧产生的内应力并提高其机械性能。连续退火的工艺流程如图1 所示&#xff0c;一般包括加热、保温、缓冷…

Datawhale AI 夏令营 Task1

记录第一次参加Kaggle上的比赛&#xff0c;通过一站式的教程&#xff0c;没有一点阻碍的跑通了baseline 夏令营方向的选择 我选择的夏令营是关于CV方向的&#xff0c;因为本身对于cv方向比较感兴趣&#xff0c;而且这次夏令营的方式我很喜欢&#xff0c;通过比赛来促进学习&a…