QT:事件机制

一、事件机制

qt的核心机制:对象树、信号和槽、事件机制

1.1概念

就是当这件事情发生时,自动执行对应的功能代码。该某块功能代码是虚函数,只需重写该虚函数,即可执行重写的代码。

1.2事件处理简介

1. 什么是事件? (重点)

        事件是由窗口系统或者自身产生的,用以响应所发生的 各类事情,比如用户按下并释放了键盘或>者鼠标、窗口因 暴露而需要重绘、定时器到时而应有所动作,等等。

        从某种意义上讲,事件比信号更原始,甚至可以认为大多 数信号其实都是由事件产生的。比如一个下压式按钮首先 感受到的是鼠标事件, 在进行必要的处理以产生按钮下沉 继而弹起的视觉效果之后,才会发射 clicked()信号。

 2. 如何处理事件? (重点)

     myWnd(自定义类) -继承-> QWidget -继承-> QObject

1> 当事件发生时,首先被调用的是QObject类中的虚函数event(), 其 QEvent型参数标识了具体的事件类型。

bool QObject:: event (QEvent* e){if (e == mouseEvent){void QWidget::mousePressEvent (QMouseEvent* e)void QWidget:: mouseReleaseEvent (QMouseEvent* e)}if(e == keyEvent){void QWidget::keyPressEvent (QMouseEvent* e)void QWidget:: keyReleaseEvent (QMouseEvent* e)}}

2> 作为QObject类的子类, QWidget类覆盖了其基类中的 event()虚函数,并根据具体事件调用具体事件处理函数

       void QWidget::mousePressEvent (QMouseEvent* e)void QWidget::mouseReleaseEvent (QMouseEvent* e)void QWidget::keyPressEvent (QMouseEvent* e)void QWidget:: keyReleaseEvent (QMouseEvent* e)void QWidget::paintEvent (QPaintEvent* e):

3> 而这些事件处理函数同样也是虚函数,也可以被 QWidget类 的子类覆盖,以提供针对不同窗口部件类型的事件处理

4> 组件的使用者所关心的往往是定义什么样的槽处理什么样的信号, 而组件的实现者更关心覆盖哪些事件处理函数

 1.3 事件处理函数由来

QObject类 提供了哪些可以重写的虚函数:

[virtual] bool QObject::event(QEvent *e) // 参数:事件的类型

QWidgets类, 提供了哪些可以重写的虚函数:

[override virtual protected] bool QWidget::event(QEvent *event)[virtual protected] void QWidget::keyPressEvent(QKeyEvent *event)[virtual protected] void QWidget::keyReleaseEvent(QKeyEvent *event)[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event)[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event)[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event)[virtual protected] void QWidget::mouseDoubleClickEvent(QMouseEvent *event)[virtual protected] void QObject::timerEvent(QTimerEvent *event)

QPainter类 ---> 画家类

 void SimpleExampleWidget::paintEvent(QPaintEvent *){QPainter painter(this);painter.setPen(Qt::blue);painter.setFont(QFont("Arial", 30));painter.drawText(rect(), Qt::AlignCenter, "Qt");}

 二、定时器事件 QTimerEvent

2.1 作用

让系统每隔一定的时间,自动执行某块功能代码。

2.2 基于事件机制(涉及的函数 )

1、启动定时器

startTimer(int sec); //启动一个定时器,给定毫秒数,返回值是该定时器的id 每隔一定的时间,自动执行timerEvent()函数。

2、关闭定时器

killTimer(int id); //关闭定时器,关闭哪个定时器以id号为准 

3、定时器超时

timerEvent(); //定时器超时时,自动执行的功能代码 --->是QWidget提供的虚函数

 案例

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//    id2 = startTimer(2000);
}Widget::~Widget()
{delete ui;
}//定时器超时时,自动执行的功能函数
void Widget::timerEvent(QTimerEvent *e)
{   //判断哪个定时器超时if(e->timerId() == id){//    static int num =0;//    ui->label->setNum(++num);//获取系统时间QTime sys_time = QTime::currentTime();//将时间转换成字符串QString t = sys_time.toString("hh--mm--ss");//将系统时间放入lab中ui->label->setText(t);//文本居中显示ui->label->setAlignment(Qt::AlignCenter);}}//启动按钮对应的槽函数
void Widget::on_pushButton_clicked()
{if(ui->pushButton->text() == "启动"){//启动一个定时器id = startTimer(1000); //每隔1秒钟,自动执行timerEvent()函数//将文本设置“关闭”ui->pushButton->setText("关闭");}else{//关闭定时器killTimer(id);//将文本设置“启动”ui->pushButton->setText("启动");}
}

2.4 基于属性版本(信号和槽)

  • QTime 时间类
  • QTimeEvent 定时器事件类
  • QTimer 时间事件类

1、使用QTimer类实例化一个对象

2、用该对象调用成员函数 start(int sec); //启动一个定时器,每个一定毫秒,自动触发timeout信号

3、将timeout信号连接到自定的槽函数中

4、用该对象调用成员函数stop(); //关闭定时器

案例

头文件:
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include<QTime> //时间类
#include<QTimer> //时间事件类
#include<QTimerEvent> //定时器事件类QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();//重写timerEvent()函数的声明void timerEvent(QTimerEvent *e);private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();void timeout_slot();private:Ui::Widget *ui;//定义一个定时器的idint id;// 实例化一个时间事件对象QTimer *timer;
};
#endif // WIDGET_H
 源文件:
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget), timer(new QTimer(this)) //给时间事件对象实例化空间
{ui->setupUi(this);// id2 = startTimer(2000);//将系统提供的timeout信号和自定义槽连接connect(timer, &QTimer::timeout, this, &Widget::timeout_slot);
}Widget::~Widget()
{delete ui;
}//定时器超时时,自动执行的功能函数
void Widget::timerEvent(QTimerEvent *e)
{//判断哪个定时器超时if(e->timerId() == id){//    static int num =0;//    ui->label->setNum(++num);//获取系统时间QTime sys_time = QTime::currentTime();//将时间转换成字符串QString t = sys_time.toString("hh--mm--ss");//将系统时间放入lab中ui->label->setText(t);//文本居中显示ui->label->setAlignment(Qt::AlignCenter);}
}//启动按钮对应的槽函数
void Widget::on_pushButton_clicked()
{if(ui->pushButton->text() == "启动"){//启动一个定时器id = startTimer(1000); //每隔1秒钟,自动执行timerEvent()函数//将文本设置“关闭”ui->pushButton->setText("关闭");}else{//关闭定时器killTimer(id);//将文本设置“启动”ui->pushButton->setText("启动");}
}//启动按钮2对应的槽函数
void Widget::on_pushButton_2_clicked()
{if(ui->pushButton_2->text() == "启动"){//启动一个定时器timer->start(1000);//每隔1秒钟,自动出发timeout信号//将文本设置“关闭”ui->pushButton_2->setText("关闭");}else{//关闭定时器timer->stop();//将文本设置“启动”ui->pushButton_2->setText("启动");}
}void Widget::timeout_slot()
{//获取系统时间QTime sys_time = QTime::currentTime();//将时间转换成字符串QString t = sys_time.toString("hh--mm--ss");//将系统时间放入lab中ui->label_2->setText(t);//文本居中显示ui->label_2->setAlignment(Qt::AlignCenter);
}

 三、键盘事件 QKeyEvent

3.1 概念

当程序员使用键盘(按下,抬起)时,自动执行对应的功能函数。

3.2 重写的功能函数

[virtual protected] void QWidget::keyPressEvent(QKeyEvent *event); //键盘按下事件函数的声明
[virtual protected] void QWidget::keyReleaseEvent(QKeyEvent *event); //键盘抬起事件函数的声明

 3.3 QKeyEvent中常用的函数

int key() const     // 键盘上键对应的键值QString text() const //键盘上键对应的文本,比如大小写

案例:

Ui界面

 头文件:
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include<QKeyEvent> //键盘事件类QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();//键盘按下事件函数的声明void keyPressEvent(QKeyEvent *event) override;//键盘抬起事件函数的声明void keyReleaseEvent(QKeyEvent *event) override;private:Ui::Widget *ui;
};
#endif // WIDGET_H

 源文件:
#include "widget.h"
#include "ui_widget.h"
#include<QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;
}//重写键盘按下事件函数的实现
void Widget::keyPressEvent(QKeyEvent *event)
{//qDebug() << "张峪熙不要睡了。。。";//ui->label->setText(QString("%1被按下").arg(event->text()));QString s = QString("%1被按下").arg(event->text());ui->label->setText(s);//判断是否是'W'按下 往上跑switch (event->key()){case 'W':{if(ui->label->y()<0-ui->label->height()){ui->label->move(ui->label->x(), this->height());}ui->label->move(ui->label->x(),ui->label->y()-5);}}
}
//重写键盘抬起事件函数的实现
void Widget::keyReleaseEvent(QKeyEvent *event)
{QString s = QString("%1被抬起").arg(event->text());ui->label->setText(s);
}

四、鼠标事件 QMouseEvent

4.1 概念

当程序员使用鼠标时,自动执行对应的功能函数。

4.2 重写的功能函数

[virtual protected] void QWidget::mouseDoubleClickEvent(QMouseEvent *event);//鼠标双击事件函数
[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event);//鼠标移动事件函数
[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event);//鼠标按下事件函数
[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event);//鼠标抬起事件函数

4.3 QMouseEvent中常用的函数

button()  ------>使用鼠标时,该函数判断哪个键被按下
buttons() ------>针对于鼠标移动时,判断哪个键被按下
pos()    -------->当前鼠标所在的位置
globalPos()  ------->鼠标针对于全局的坐标点
x()   ------->x坐标点
y()   ------->y坐标点

案例:

头文件:
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include<QKeyEvent> //键盘事件类
#include<QMouseEvent> //鼠标事件类QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void mousePressEvent(QMouseEvent *event) override;//鼠标按下事件函数声明void mouseReleaseEvent(QMouseEvent *event) override;//鼠标抬起事件函数声明void mouseDoubleClickEvent(QMouseEvent *event) override;//鼠标双击事件函数声明void mouseMoveEvent(QMouseEvent *event) override;//鼠标移动事件函数声明private:Ui::Widget *ui;
};
#endif // WIDGET_H
源文件:
#include "widget.h"
#include "ui_widget.h"
#include<QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//开启鼠标追踪功能this->setMouseTracking(true);
}Widget::~Widget()
{delete ui;
}//重写鼠标按下事件函数实现
void Widget::mousePressEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){ui->label->setText(QString("左键被按下(%1,%2)").arg(event->x()).arg(event->y()));}else if(event->button() == Qt::RightButton){ui->label->setText(QString("右键被按下(%1,%2)").arg(event->x()).arg(event->y()));}else if(event->button() == Qt::MidButton){ui->label->setText(QString("中间键被按下(%1,%2)").arg(event->x()).arg(event->y()));}
}
//重写鼠标抬起事件函数实现
void Widget::mouseReleaseEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){ui->label->setText(QString("左键被抬起(%1,%2)").arg(event->x()).arg(event->y()));}else if(event->button() == Qt::RightButton){ui->label->setText(QString("右键被抬起(%1,%2)").arg(event->x()).arg(event->y()));}else if(event->button() == Qt::MidButton){ui->label->setText(QString("中间键被抬起(%1,%2)").arg(event->x()).arg(event->y()));}
}
//重写鼠标双击事件函数实现
void Widget::mouseDoubleClickEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){ui->label->setText(QString("左键被双击(%1,%2)").arg(event->x()).arg(event->y()));}else if(event->button() == Qt::RightButton){ui->label->setText(QString("右键被双击(%1,%2)").arg(event->x()).arg(event->y()));}else if(event->button() == Qt::MidButton){ui->label->setText(QString("中间键被双击(%1,%2)").arg(event->x()).arg(event->y()));}
}
//重写鼠标移动事件函数实现
void Widget::mouseMoveEvent(QMouseEvent *event)
{ui->label->move(event->pos());
}

纯净窗口的移动

头文件:

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include<QMouseEvent> //鼠标事件类
#include<QPoint> //向量类QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void mouseMoveEvent(QMouseEvent *event) override;void mousePressEvent(QMouseEvent *event) override;private:Ui::Widget *ui;QPoint p; //记录鼠标在当前窗口的位置
};
#endif // WIDGET_H

源文件:

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//设置纯净窗口this->setWindowFlag(Qt::FramelessWindowHint);
}Widget::~Widget()
{delete ui;
}void Widget::mouseMoveEvent(QMouseEvent *event)
{//判断是否是左键被按下if(event->buttons() == Qt::LeftButton){//窗口移动this->move(event->globalPos() - p);//全局坐标         当前窗口坐标}}
void Widget::mousePressEvent(QMouseEvent *event)
{p = event->pos(); //鼠标在当前窗口的坐标
}

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

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

相关文章

【教学类-76-01】20240820书包01(图案最大化)

背景需求 通义万相生成图片&#xff0c;把图案最大化的方法&#xff08;切掉白边&#xff09; 【教学类-75-01】20240817“通义万相图片最大化透明png”的修图流程-CSDN博客文章浏览阅读1.6k次&#xff0c;点赞56次&#xff0c;收藏17次。【教学类-75-01】20240817“通义万相…

【Android 笔记】记移植OpenCV4.8图像人脸识别

前言 因业务需要&#xff0c;使用大屏端摄像头捕获图像&#xff0c;且要识别图像中人脸的数目以及从中随机抽取一人。 业务流程如下&#xff0c;调用摄像头预览、拍照&#xff0c;使用OpenCV库进行人脸识别&#xff0c;将识别到的人脸使用矩形框绘制出来&#xff0c;从识别的人…

【秋招笔试】8.18大疆秋招(第三套)-三语言题解

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 编程一对一辅导 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收…

STM32CubeMX 配置串口通信 HAL库

一、STM32CubeMX 配置串口 每个外设生成独立的 ’.c/.h’ 文件 不勾&#xff1a;所有初始化代码都生成在 main.c 勾选&#xff1a;初始化代码生成在对应的外设文件。 如 GPIO 初始化代码生成在 gpio.c 中。 二、重写fputc函数 ​ #include <stdio.h>#ifdef __GNUC__#def…

无人机之固定翼无人机的组成

固定翼无人机是根据空气动力学原理设计机翼的形状&#xff0c;靠动力装置产生推力或者拉力&#xff0c;使无人机获得一定速度后&#xff0c;会导致空气在飞机上下表面的压力不同&#xff0c;进而产生升力&#xff0c;其升力主要来源于固定的机翼。大多数都是由机翼、机身、尾翼…

FastHTML:使用 Python 彻底改变 Web 开发

什么是 FastHTML&#xff1f;&#x1f310; FastHTML 是一个现代 Python Web 应用程序框架&#xff0c;其真正目的是让 Python 开发人员轻松进行 Web 开发。它大大减少了对 JavaScript 和 CSS 构建交互式和可扩展 Web 应用程序的依赖。FastHTML 通过使用 Python 对象来表示 HTM…

python 捕获异常

捕获指定异常 e 是保存的异常信息 捕获多个异常

全国大学生数学建模比赛——时间序列(详细解读)

全国大学生数学建模比赛中&#xff0c;时间序列分析是一种重要的方法。以下是对时间序列在该比赛中的详细解读&#xff1a; 一、时间序列的概念 时间序列是按时间顺序排列的一组数据。在数学建模中&#xff0c;时间序列数据通常反映了某个现象随时间的变化情况。例如&#xf…

使用vs配置opencv环境(属性表方法)

opencv官网&#xff1a;https://opencv.org/releases/ 老手回忆&#xff08;新建属性表&#xff09; Step1: 安装VS&#xff0c;安装openCV Step2: 新建项目&#xff0c;新建项目属性表&#xff0c;debug|x64新建属性&#xff0c;命好名字 Step3: VC目录-包含目录中添加: 安装…

经典游戏,用java实现的坦克大战小游戏

今天给大家分享一个使用java编写的坦克大战小游戏&#xff0c;整体还是挺好玩的&#xff0c;通过对这款游戏的简单实现&#xff0c;加深对java基础的深刻理解。 一、设计思路 1.坦克大战小游戏通过java实现&#xff0c;其第一步需要先绘制每一关对应的地图&#xff0c;地图包括…

WPF中RenderTransform,LayoutTransform区别

RenderTransform RenderTransform 是在渲染阶段应用的变换。它不会影响控件的布局&#xff0c;只会影响控件的外观。常用于动画和视觉效果。 • 应用时机&#xff1a;在控件已经完成布局之后。 • 影响范围&#xff1a;仅影响控件的外观&#xff0c;不影响布局。 • 常见用途&…

探索 HarmonyOS 的层叠布局:灵活的 Stack 容器

在应用开发中&#xff0c;灵活的布局设计是提高用户体验的关键之一。HarmonyOS 提供了丰富的布局组件&#xff0c;其中层叠布局&#xff08;Stack Layout&#xff09;是一个强大的工具&#xff0c;可以帮助开发者轻松实现元素的重叠显示。本文将深入探讨 Stack 容器的功能和应用…

【设计模式】六大原则-下

❓首先什么是设计模式&#xff1f; &#x1f635;相信刚上大学的你和我一样&#xff0c;在学习这门课的时候根本不了解这些设计原则和模式有什么用处&#xff0c;反而不如隔壁的C更有意思&#xff0c;至少还能弹出一个小黑框&#xff0c;给我个hello world。 ✨ 如何你和我一样…

ArcGIS Pro基础:状态栏显示栏的比例尺设置和经纬度位置

上图所示&#xff0c;界面下方最左侧是显示的比例尺&#xff0c;可以进行选择设置&#xff0c;也可以进行自定义设置 上图所示&#xff0c;可以手动录入比例尺&#xff0c;同时也可以对比例尺设置别名&#xff0c;比如【实验1】作为特定比例尺的标记 如上图所示&#xff0c;可以…

KEEPALIVED高可用集群最详解

目录 一、高可用集群 1.1 集群的类型 1.2 实现高可用 1.3 VRRP&#xff1a;Virtual Router Redundancy Protocol 1.3.1 VRRP相关术语 1.5.2 VRRP 相关技术 二、部署KEEPALIVED 2.1 keepalived 简介 2.2 Keepalived 架构 2.3 Keepalived 环境准备 2.3.1 实验环境 2…

嵌入式初学-C语言-二七

文件操作 概述&#xff1a; 什么是文件&#xff1a; 是保存在外存储器&#xff08;磁盘&#xff0c;u盘&#xff0c;移动硬盘等等&#xff09;上的数据的集合。 文件操作体现在哪几个方面&#xff1a; 文件内容的读取文件内容的写入 数据的读取和写入可被视为针对文件进行…

Day42 | 739. 每日温度 496.下一个更大元素 I 503.下一个更大元素II

语言 Java 739. 每日温度 每日温度 题目 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该…

关于windows环境使用nginx的一些性能问题

遇到的问题 最近在一个windows环境中部署nginx&#xff0c;遇到了以下问题&#xff1a; 1. nginx启动了九个线程&#xff08;1master8woekr&#xff09;&#xff0c;但是所有链接都被1个woker接收&#xff0c;其余worker不工作 2. 用户端访问web很慢&#xff0c;登录服务器使…

k8s搭建

环境&#xff1a; 操作系统&#xff1a;win10 虚拟机&#xff1a;virtual box linux发行版&#xff1a;CentOS7.9 linux内核(使用uname -r查看)&#xff1a;3.10.0-957.el7.x86_64 master和node节点通信的ip(master)&#xff1a; 10.0.0.198 0.检查配置 本次搭建的集群共三个节…

deepspeed的并行模式介绍笔记

1.整体框架 2.并行模式 1.数据并行DDP 数据切分以后&#xff0c;分开单张卡训练得到参数&#xff0c;然后综合在单卡计算。 要点&#xff1a;前向计算和反向计算两步骤走并汇总。 1.前向计算 需要留一块主卡一定空间用于综合。 2.反向传播 利用前向传播的汇总参数得到各个…