Qt入门7——Qt事件

news2025/1/10 21:00:29

目录

1. Qt事件介绍:

2. 事件的处理 

示例1:鼠标进入(enterEvent)与离开事件(leaveEvent)

示例2:鼠标点击事件(mousePressEvent)

示例3:鼠标移动事件(mouseMoveEvent)

3. 按键事件

4. 定时器

5. 窗口事件


1. Qt事件介绍:

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

2. 事件的处理 

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

示例1:鼠标进入(enterEvent)与离开事件(leaveEvent)

处理鼠标进入与离开事件

1.新建Qt项目,基类选择QWidget,同时勾选UI界面文件

2. 在ui文件添加label控件

 3. 创建QLabel的子类,重写enterEvent和leaveEvent

①:

②:

此时项目多出两个新文件:

4. 为了方便给label指定父对象,调整一下构造函数:

5.函数重写:在"label.h"中:

(注意:重写函数时,要确保函数名字和参数列表完全一致 ,谨防拼写错误,为避免错误,可以在帮助文档查找目标函数,复制粘贴即可)

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

6. 在"label.cpp"重写enterEvent与leaveEvent方法:

(按alt+回车键转到函数定义)

void Label::enterEvent(QEvent *event)
{
    (void) event;//躲避编译器警告
    qDebug() << "enterEvent";
}

void Label::leaveEvent(QEvent *event)
{
    (void) event;//躲避编译器警告
    qDebug() << "leaveEvent";
}

此时执行程序,其实并没有起到效果,这是因为此时界面上的label并不是我们定义的Label类的实例,其仍然是系统的QLabel创建的实例。

那么问题来了,此时也只能从界面上拖动QLabel来创建实例呀!如何才能使界面上的label是来自我们自己定义的Label类呢?步骤继续:

7. 回到ui界面:

效果如图:


学到了这里,我们再来回顾一下在Qt入门3——常用控件1中所写的“给女神表白的程序”,当时鼠标点击的时候按钮才会移动,现在我希望鼠标进入按钮,按钮就随机移动,代码如下:

1.按照如上步骤,添加一个Button类,再将“拒绝”按钮提升为Button类

2.重写enterEvent:

#include "button.h"

Button::Button(QWidget* parent) : QPushButton(parent)
{
    srand(time(0));
}

void Button::enterEvent(QEvent *event)
{
    (void) event;
    //获取父窗口
    QWidget* parentwidget = this->parentWidget();
    //获取父窗口可用区域的大小
    int width = parentwidget->geometry().width();
    int height = parentwidget->geometry().height();

    int x = rand() % width;
    int y = rand() % height;

    this->move(x,y);
}

效果如图:按钮还没来得及点击就跑了:


示例2:鼠标点击事件(mousePressEvent)

当鼠标点击时,获取相应的坐标值

1. 创建两个label:

2. 按照示例1的7,将下面的label提升。

3. 在label.h中创建一个私有变量QString类型的私有变量coordText

4. 重写mousePressEvent函数:(详细步骤参考示例1)

void Label::mousePressEvent(QMouseEvent *ev)
{
    if(ev->button() == Qt::LeftButton){
        coordText = QString("此处以label为准的坐标为:(%1, %2)").arg(ev->x()).arg(ev->y());
    }else if(ev->button() == Qt::RightButton){
        coordText = QString("此处以主窗口为准的坐标:(%1, %2)").arg(ev->globalX()).arg(ev->globalY());
    }
    this->setText(coordText);
}

效果如图:

鼠标释放事件(mouseReleaseEvent)与鼠标双击事件(mouseDoubleClickEvent)与示例2相同,不过是需要重写的函数不同罢了,此处不再演示。


示例3:鼠标移动事件(mouseMoveEvent)

此示例让鼠标移动事件发生在整个窗口,所以不再自定义类。

1.在ui界面创建一个label来显示鼠标移动的坐标

2.重写mouseMoveEvent:

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    ui->label->setText("(" + QString::number(event->x()) + "," + QString::number(event->y()) + ")");
}

3. 

此时运行程序,不会有任何反应,这是因为鼠标移动不同于鼠标按下和释放,随便移动一下鼠标就会产生大量的鼠标移动事件。当进行捕获事件时,尤其是执行一些复杂的逻辑时,程序的负担会很重,可能会产生卡顿的情况。所以默认情况下Qt不会对鼠标移动事件进行跟踪,除非显式地告诉Qt:

//在构造函数中将setMouseTracking设为true
this->setMouseTracking(true);

效果如图:


示例4:鼠标滚轮滑动事件(wheelEvent)

1.在ui界面创建一个label来显示鼠标移动的坐标

2.重写wheelEvent

void Widget::wheelEvent(QWheelEvent *event)
{
    //delta()获取到这次事件鼠标滚轮滚动了多远
    ui->label->setText(QString::number(event->delta()));
}

效果如图:滚动一次为120像素

3. 按键事件

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

可以在Qt帮助文档中查看QKeyEvent类:

组合按键:

示例:

void Widget::keyPressEvent(QKeyEvent *event)
{
    //用label显示按下的按键对应的value
    ui->label->setText(QString::number(event->key()));
    //用label_2显示按下的单个按键
    if(event->key() == Qt::Key_A){
        ui->label_2->setText("按下了A键");
    }
    //用label_3显示按下的组合按键
    if(event->key() == Qt::Key_A && event->modifiers() == Qt::ControlModifier){
        ui->label_3->setText("按下了ctrl+A键");
    }
}

效果如图:

4. 定时器

Qt 中在进行窗口程序的处理过程中,经常要周期性的执行某些操作,或者制作一些动画效果,使用定时器就可以实现。所谓定时器就是在间隔一定时间后,去执行某一个任务。

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

QTimerEvent类用来描述一个定时器事件。在使用时需要通过startTimer()函数来开启一个定时器,这个函数需要输入一个以毫秒为单位的整数作为参数来表明设定的时间,它返回的整型值代表 这个定时器。当定时器溢出时(即定时时间到达)就可以在timerEvent()函数中获取该定时器的编号来进行相关操作;

QTimer类来实现⼀个定时器,它提供了更高层次的编程接口,如:可以使用信号和槽,还可以设置只运行一次的定时器。

示例:

1.ui界面创建定时器

2. 重写timerEvent

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

    //开启定时器事件
    //此处timerId是一个定时器的身份标识
    timerId = this->startTimer(1000);//timeId为此类的私有变量
}

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);
}

效果如图:

5. 窗口事件

窗口事件有窗口移动事件(moveEvent)和窗口大小改变事件(resizeEvent)。

示例:

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

    QVBoxLayout* layout = new QVBoxLayout();
    layout->addWidget(ui->label);
    layout->addWidget(ui->label_2);
    this->setLayout(layout);
}

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

void Widget::moveEvent(QMoveEvent *event)
{
    QPoint pos = event->pos();
    QString text = QString("窗口现在的坐标为(%1,%2)").arg(pos.x()).arg(pos.y());
    ui->label->setText(text);
}

void Widget::resizeEvent(QResizeEvent *event)
{
    QSize size = event->size();
    QString text = QString("窗口现在的长度为:%1,宽度为:%2").arg(size.width()).arg(size.height());
    ui->label_2->setText(text);
}

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

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

相关文章

PyQt事件机制练习

一、思维导图 二、代码 import sysfrom PyQt6.QtTextToSpeech import QTextToSpeech from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QLineEdit from PyQt6 import uic from PyQt6.QtCore import Qt, QTimerEvent, QTimeclass MyWidget(QWidget):d…

【河南】《关于省级政务信息化建设项目支出预算标准的规定(试行)》(豫财预〔2020〕81号)-省市费用标准解读系列25

《关于省级政务信息化建设项目支出预算标准的规定(试行)》&#xff08;豫财预 〔2020〕81号&#xff09;是河南省财政厅2020年8月27日发布的信息化项目预算标准&#xff08;了解更多可直接关注我们咨询&#xff09;。该标准旨在加强河南省省级部门预算管理&#xff0c;规范省级…

oscp备考,oscp系列——Kioptix Level 3靶场

Kioptix Level 3 oscp备考&#xff0c;oscp系列——Kioptix Level 3靶场 nmap扫描 主机发现 └─# nmap -sn 192.168.80.0/24 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-09 00:33 CST Nmap scan report for 192.168.80.1 Host is up (0.00014s latency). MAC…

活动|华院计算董事长宣晓华应邀出席2024科创大会并作圆桌嘉宾

2024科创大会在上海举行&#xff0c;由中央广播电视总台和上海市人民政府共同主办。本次大会以“创新驱动 新质未来”为主题&#xff0c;来自知名院校、科研机构的专家学者以及科技企业、金融机构的相关负责人共聚一堂&#xff0c;探讨人工智能、生物医药等产业应用前景&#x…

Robust Univariate Mean Estimation算法简介

Robust Univariate Mean Estimation 是一种统计算法&#xff0c;主要用于在单变量场景中估计样本的均值&#xff0c;同时对异常值&#xff08;outliers&#xff09;具有鲁棒性。传统的均值估计使用样本的算术平均值&#xff0c;但它对异常值高度敏感。为了缓解这个问题&#xf…

C/C++流星雨

系列文章 序号直达链接1C/C爱心代码2C/C跳动的爱心3C/C李峋同款跳动的爱心代码4C/C满屏飘字表白代码5C/C大雪纷飞代码6C/C烟花代码7C/C黑客帝国同款字母雨8C/C樱花树代码9C/C奥特曼代码10C/C精美圣诞树11C/C俄罗斯方块12C/C贪吃蛇13C/C孤单又灿烂的神-鬼怪14C/C闪烁的爱心15C/C…

MySQL——buffer poll

为什么要有buffer poll&#xff1f; 如果没有buffer poll&#xff0c;每次读取数据的时候都是从磁盘上读的&#xff0c;这样效率是很差的的。 所以有了提高效率的方式&#xff0c;就加上了一个缓存——buffer poll 所以&#xff0c;当我们读取数据的时候就有以下的方式 当读…

2025年山东省职业院校技能大赛“信息安全管理与评估”(山东省) 任务书

2025年山东省职业院校技能大赛“信息安全管理与评估”(山东省 任务书 模块一网络平台搭建与设备安全防护任务1&#xff1a;网络平台搭建 &#xff08;50分&#xff09;任务2&#xff1a;网络安全设备配置与防护&#xff08;250分&#xff09; 模块二网络安全事件响应、数字取证…

ERROR: KeeperErrorCode = NoNode for /hbase/master

原因分析 通过上面的情景模拟&#xff0c;我们可以看到报错的原因在于zookeeper中出现问题&#xff0c;可能是zookeeper中的/hbase/master被删除&#xff0c;或者是在hbase集群启动之后重新安装了zookeeper&#xff0c;导致zookeeper中的/hbase/master节点数据异常。 1. 停止…

ElasticSearch7.8学习笔记

1. ElasticSearch概述 1.1 ElasticSearch是什么 Elaticsearch&#xff0c;简称为 ES&#xff0c;ES 是一个开源的高扩展的分布式全文搜索引擎&#xff0c;是整个Elastic Stack 技术栈的核心。它可以近乎实时的存储、检索数据&#xff1b;本身扩展性很好&#xff0c;可以扩展到…

CSS制作字体炫彩效果

目录 序言一、思路二、代码实现 序言 本节内容主要来讲解一下炫彩字体的实现&#xff0c;主要通过使用 background-clip以及background-position来实现&#xff0c;那么话不多说开始本节内容的学习吧&#xff01; 一、思路 添加盒子以及内容使用 background-clip属性&#x…

如何防止短信盗刷和短信轰炸?

短信盗刷和短信轰炸是项目开发中必须要解决的问题之一&#xff0c;它的优先级不亚于 SQL 注入的问题&#xff0c;同时它也是面试中比较常见的一个经典面试题&#xff0c;今天我们就来看下&#xff0c;如何防止这个问题。 1.概念介绍 短信盗刷和短信轰炸的概念如下&#xff1a…

ios逆向某新闻 md5+aes

本期的案例比较简单&#xff0c;也许是ios逆向算法本来就比较简单的原因&#xff0c;所以前面我就多扯一些爬虫和逆向的东西。之前写的文章都是js逆向和android逆向的案例&#xff0c;这也是首篇ios的案例&#xff0c;所以会从入门开始讲起。 3大逆向对比 首先爬虫工程师大部…

SpringBoot【一】零基础入门 springboot 及 idea 搭建

一、前言 springboot是什么&#xff1f; Spring Boot是由Pivotal团队提供的全新框架&#xff0c;其设计目的是用来简化新Spring应用的初始搭建以及开发过程。 该框架使用了特定的方式来进行配置&#xff0c;从而使开发人员不再需要定义样板化的配置。用我的话来理解&#xff0…

2024年超大跨径钢结构桥梁创新技术论坛暨钢桥联盟年度工作会议顺利召开

12月5日&#xff0c;由中交公路规划设计院有限公司、装配化钢结构桥梁产业技术创新战略联盟主办&#xff0c;保利长大工程有限公司、中交第二航务工程局有限公司、中交第二公路工程局有限公司、中交路桥建设有限公司、中交西安筑路机械有限公司、南京现代综合交通实验室、巨力锁…

win10上部署win11记事本

win10上部署win11记事本 原因 win10的老用户们, 不肯升级win11, 绝对是有留恋的东西吧,就想win7用户那样, 但是win11在日益更新, 特别是记事本, 增加了很多好用的功能, 比如多标签页, 但是不想升级win11, 还想用, 怎么办? 我在网上找到了解决方案, 接下来, 我们来操作一下吧…

记录:ubuntu24.04源码安装nginx

一. 下载Nginx源码 两个地址二选一即可 Nginx官网Nginx官网 Github eg&#xff1a;nginx-1.27.3.tar.gz 下载到 ubuntu24.04 的 Downloads &#xff0c;解压 cd Downloads tar -zxvf nginx-1.27.3.tar.gz二. 编译安装 Note: 编译最好用 root 权限&#xff0c; 使用下面命令…

【前端】深入理解 JavaScript 中的数组与对象

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: 前端 文章目录 &#x1f4af;前言&#x1f4af;数组与对象的基本概念数组&#xff08;Array&#xff09;数组示例 对象&#xff08;Object&#xff09;对象示例 &#x1f4af;数组与对象的对比核心区别如何选择&#…

31.下一个排列 python

下一个排列 题目题目描述示例 1&#xff1a;示例 2&#xff1a;示例 3&#xff1a;提示&#xff1a;题目链接 题解解题思路python实现代码解释&#xff1a;提交结果 题目 题目描述 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如&#xff0c;arr [1,2,3…

Codeforces Round 992 (Div. 2)

这场cf只在b卡了一下&#xff0c;因为b真是犯蠢了&#xff0c;我以为会向下取整&#xff0c;结果是完全就不取整&#xff0c;或者说是向上取整&#xff0c;卡了我半个小时&#xff0c;要不是紧急看了题一下&#xff0c;昨天那场就毁了 话不多说&#xff0c;直接开讲 A. Game …