当前位置: 首页 > news >正文

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(); //鼠标在当前窗口的坐标
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 计算机基础知识复习8.14
  • redis随笔记
  • 位运算使用
  • 汇编语言lea指令取数组偏移地址
  • C++:priority_queue类
  • JavaScript class和正则
  • 10天速通Tkinter库——Day 5:使用config进行OptionMenu美化
  • Minio web控制台实现授权管理
  • 使用 nginx 搭建代理服务器(正向代理 https 网站)指南
  • 【Java】—— 使用Java编写程序找出100以内的质数
  • 理解类方法和静态方法:Python 中的高级函数
  • Nginx负载均衡调度状态
  • 哇哦--一起学习接口叭
  • XSS总结知识点+例题实操
  • 探索 HarmonyOS 的层叠布局:灵活的 Stack 容器
  • 时间复杂度分析经典问题——最大子序列和
  • 【笔记】你不知道的JS读书笔记——Promise
  • 2017届校招提前批面试回顾
  • Android框架之Volley
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • JWT究竟是什么呢?
  • Linux CTF 逆向入门
  • windows-nginx-https-本地配置
  • 阿里云前端周刊 - 第 26 期
  • 番外篇1:在Windows环境下安装JDK
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 讲清楚之javascript作用域
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 深度解析利用ES6进行Promise封装总结
  • 一些关于Rust在2019年的思考
  • 智能合约开发环境搭建及Hello World合约
  • - 转 Ext2.0 form使用实例
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • (11)MSP430F5529 定时器B
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (创新)基于VMD-CNN-BiLSTM的电力负荷预测—代码+数据
  • (七)理解angular中的module和injector,即依赖注入
  • (五)activiti-modeler 编辑器初步优化
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • .bashrc在哪里,alias妙用
  • .naturalWidth 和naturalHeight属性,
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .net开发日常笔记(持续更新)
  • .NET框架设计—常被忽视的C#设计技巧
  • .NET是什么
  • @Autowired和@Resource装配
  • [] 与 [[]], -gt 与 > 的比较
  • [【JSON2WEB】 13 基于REST2SQL 和 Amis 的 SQL 查询分析器
  • [1159]adb判断手机屏幕状态并点亮屏幕
  • [Algorithm][综合训练][kotori和气球][体操队形][二叉树中的最大路径和]详细讲解
  • [Angular 基础] - 数据绑定(databinding)
  • [Angular] 笔记 9:list/detail 页面以及@Output