QT的事件机制

QT的事件机制

文章目录

    • QT的事件机制
  • 1、QT的事件机制。
  • 2、QT事件的整体流程。
    • 1、事件处理函数。
      • 1、鼠标按下与鼠标释放事件。
      • 2、事件的接收与忽略(accept()和ignore()函数)。
    • 2.事件的分发enevt()
      • 1、事件分发的dome。
      • 2、enevt事件的缺点。
    • 3、事件的过滤器。
  • 3、总结


1、QT的事件机制。

事件(event)是由系统或者 Qt 本身在不同的时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件。一些事件是****用户操作做出响应时发出,如键盘事件等;另一些事件则是由系统自动发出,如计时器事件。

在前面我们也曾经简单提到,Qt 程序需要在main()函数创建一个QApplication对象,然后调用它的exec()函数。这个函数就是开始 Qt 的事件循环。在执行exec()函数之后,程序将进入事件循环来监听应用程序的事件。当事件发生时,Qt 将创建一个事件对象。Qt 中所有事件类都继承于QEvent。在事件对象创建完毕后,Qt 将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是按照事件对象的类型分派给特定的事件处理函数(event handler)。

2、QT事件的整体流程。

如图所示:
在这里插入图片描述
app.exe()--------->事件过滤器----->事件分发器-----------------》事件处理函数

下面依次从下往上介绍。

1、事件处理函数。

1、鼠标按下与鼠标释放事件。

提升一个按钮。重写鼠标按下与鼠标释放事件。
mybutton.h

#include <QWidget>
#include <QPushButton>
#include <QMouseEvent>
#include <QEvent>
class MyButton : public QPushButton
{Q_OBJECT
public:explicit MyButton(QWidget *parent = nullptr);//鼠标点击事件void mousePressEvent(QMouseEvent *ev);//鼠标释放事件void mouseReleaseEvent(QMouseEvent *ev);
signals:
};

mybutton.cpp

#include "mybutton.h"
#include <QDebug>MyButton::MyButton(QWidget *parent): QPushButton{parent}
{}void MyButton::mousePressEvent(QMouseEvent *ev)
{qDebug() << "鼠标按下" ;
}
void MyButton::mouseReleaseEvent(QMouseEvent *ev)
{qDebug() << "鼠标抬起" ;
}

结果如下:
在这里插入图片描述
注意:按钮是提升自定义mybutton类。而mybutton又是继承于QPushButton

2、事件的接收与忽略(accept()和ignore()函数)。

mybutton.h

#include <QWidget>
#include <QPushButton>
#include <QMouseEvent>
#include <QEvent>class MyButton : public QPushButton
{Q_OBJECT
public:explicit MyButton(QWidget *parent = nullptr);//鼠标点击事件void mousePressEvent(QMouseEvent *ev);signals:};

mybutton.cpp

#include "mybutton.h"
#include <QDebug>MyButton::MyButton(QWidget *parent): QPushButton{parent}
{}void MyButton::mousePressEvent(QMouseEvent *ev)
{if(ev->button() == Qt::LeftButton){qDebug() << "MyButton鼠标按下的是左键";ev->accept(); // accept 事件不会再往下传递}else // 鼠标的右键按下与鼠标的中间按键往下传递{qDebug() << "MyButton鼠标其他键按下";QPushButton::mousePressEvent(ev);}
}

myWidget.h

#include <QWidget>\
class MyWidget : public QWidget
{Q_OBJECTpublic:MyWidget(QWidget *parent = nullptr);~MyWidget();//鼠标点击事件void mousePressEvent(QMouseEvent *ev);
private:Ui::MyWidget *ui;
};

myWidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui->setupUi(this);
}MyWidget::~MyWidget()
{delete ui;
}void MyWidget::mousePressEvent(QMouseEvent *ev)
{if(ev->button() == Qt::LeftButton){qDebug() << "MyWidget鼠标左键按下";}else {qDebug() << "MyWidget鼠标其他键按下";}
}

在myWidget类与mybutton类都有重写鼠标事件。
现在accept()函数
当鼠标的左键按下时的打印:
在这里插入图片描述
对鼠标的左键按下不在往下发所以myWidget收不到
当鼠标的右键按下时的打印:
在这里插入图片描述
对鼠标的右键按下往下发所以myWidget能收到

当代码把accept()函数改成ignore()函数。鼠标左键按下事件继续往下传递。传递给了父组件mywidget

void MyButton::mousePressEvent(QMouseEvent *ev)
{if(ev->button() == Qt::LeftButton){qDebug() << "MyWidget鼠标左键按下";ev->ignore(); //忽略,事件继续往下传递,给谁传递?//事件传递给了父组件,不是给父类(基类)}else // 鼠标的右键按下与鼠标的中间按键往下传递{qDebug() << "MyButton鼠标其他键按下";QPushButton::mousePressEvent(ev);}
}

以上就是事件的接收与忽略。就是accept()函数与ignore()函数。

2.事件的分发enevt()

1、事件分发的dome。

函数原型: bool event(QEvent *ev)
event()函数主要用于事件的分发。所以,如果你希望在事件分发之前做一些操作,就可以重写这个event()函数了。
myWidget.h

#include <QWidget>
class MyWidget : public QWidget
{Q_OBJECTpublic:MyWidget(QWidget *parent = nullptr);~MyWidget();bool event(QEvent *ev);     // 重写event事件void keyPressEvent(QKeyEvent *event); //键盘按下事件void keyReleaseEvent(QKeyEvent *event);
private:Ui::MyWidget *ui;
};

myWidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui->setupUi(this);
}MyWidget::~MyWidget()
{delete ui;
}bool MyWidget::event(QEvent *e)
{if(e->type() == QEvent::KeyPress) /* 按键按下的分发 */{/* 类型转换 */QKeyEvent *env = static_cast<QKeyEvent *>(e);if(env->key() == Qt::Key_0){qDebug() << "event Qt::Key_0";return QWidget::event(e); /* 只处理按键0 */}return true; /* 其他按键不分发下去 */} else {return QWidget::event(e); /* 其他的事件都分发下去 */}
}void MyWidget::keyPressEvent(QKeyEvent *event) //键盘按下事件
{switch(event->key()) {case Qt::Key_0:qDebug() <<"Qt::Key_0";break;case Qt::Key_1:qDebug() <<"Qt::Key_1";break;}
}void MyWidget::keyReleaseEvent(QKeyEvent *event)
{qDebug() <<"MyWidget::keyReleaseEvent";
}

总结:当按下按键0按下才处理。其他按键不起作用。
按键0按下的结果:
在这里插入图片描述
其他按键按下不起作用。只打印按键释放。因为如上return QWidget::event(e); /* 其他的事件都分发下去 */
按键是否是可以打印的。如果改成return true; 就不会打印按键释放。

2、enevt事件的缺点。

在这里插入图片描述
从而引出事件过滤器。
在这里插入图片描述
在这里插入图片描述

3、事件的过滤器。

函数原型如下:virtual bool QObject::eventFilter ( QObject * watched, QEvent * event )
watched:过滤哪个控件 event:过滤哪个事件。

这个函数正如其名字显示的那样,是一个“事件过滤器”。所谓事件过滤器,可以理解成一种过滤代码。事件过滤器会检查接收到的事件。如果这个事件是我们感兴趣的类型,就进行我们自己的处理;如果不是,就继续转发。这个函数返回一个 bool 类型,如果你想将参数 event 过滤出来,比如,**不想让它继续转发,就返回 true,否则返回 false。**事件过滤器的调用时间是目标对象(也就是参数里面的watched对象)接收到事件对象之前。也就是说,如果你在事件过滤器中停止了某个事件,那么,watched对象以及以后所有的事件过滤器根本不会知道这么一个事件。
mybutton.h

#include <QPushButton>
class MyButton : public QPushButton
{Q_OBJECT
public:explicit MyButton(QWidget *parent = nullptr);void mouseMoveEvent(QMouseEvent *ev);
signals:};

mybutton.cpp

#include "mybutton.h"
#include <QDebug>MyButton::MyButton(QWidget *parent): QPushButton{parent}
{}
void MyButton::mouseMoveEvent(QMouseEvent *ev)
{qDebug() << "mouseMoveEvent";QPushButton::mousePressEvent(ev);
}

mywidget.h

#include <QWidget>
class MyWidget : public QWidget
{Q_OBJECT
public:MyWidget(QWidget *parent = nullptr);~MyWidget();//事件过滤器bool eventFilter(QObject *obj, QEvent *e);
private:Ui::MyWidget *ui;
};

mywidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui->setupUi(this);//安装过滤器ui->pushButton->installEventFilter(this);ui->pushButton->setMouseTracking(true);/* 按钮追踪 */
}MyWidget::~MyWidget()
{delete ui;
}bool MyWidget::eventFilter(QObject *obj, QEvent *e)
{if(obj == ui->pushButton){QMouseEvent *env = static_cast<QMouseEvent *>(e);//判断事件if(e->type() == QEvent::MouseMove){ui->pushButton->setText(QString("eventFilter:(%1, %2)").arg(env->x()).arg(env->y()));return true; /* 不分发 */}else{return QWidget::eventFilter(obj, e);}return true;}else{return QWidget::eventFilter(obj, e);}
}

如上 return true; /* 不分发 */ 所以 qDebug() << “mouseMoveEvent”;没有打印
如果设置return false; 事件不会过滤。就会打印mouseMoveEvent
总结:
在这里插入图片描述

3、总结

现在我们可以总结一下 Qt 的事件处理,实际上是有五个层次:
在这里插入图片描述
上面1, 2,3,点用的多。4, 5不怎么用。
事件过滤器与enevt事件,以及事件的处理函数都是虚函数继承与上层父类。我们在重写时虚函数必须继承上层父类一致。否则就不叫重写。

以上就是今天要讲的内容,QT的事件。主要理解QT从上到下的流程。

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

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

相关文章

通过本质看现象:关于Integer受内部初始化赋值范围限制而出现的有趣现象

文/朱季谦 这是我很多年前的第一篇技术博客&#xff0c;当时作为一名技术小菜鸟&#xff0c;总体而言显得很拙见&#xff0c;但也算是成长路上的一个小脚印&#xff0c;希望能在以后的日子里&#xff0c;可以对JAVA技术有一个更加深入的思考与认识。 前几天我在逛论坛的时候&a…

SSM基础入门

SSM Mybatis、Spring和SpringMVC这三个框架整合在一起完成业务功能开发 文章目录 SSM5.1 流程5.2 详细步骤5.2.1 基本配置5.2.2 功能模块开发5.2.3 测试5.2.3.1 单元测试5.2.3.2 PostMan测试 5.3 统一结果封装5.3.1 概念5.3.2 实现 5.4 统一异常处理5.4.1 异常处理器的使用5.4…

自学习算法

自学习算法是一种基于深度学习的技术&#xff0c;通过大量的数据和模型训练&#xff0c;不断优化和改进模型的表现。 具体来说&#xff0c;自学习算法包括以下几个方面&#xff1a; 1.数据预处理&#xff1a;在训练模型之前&#xff0c;需要对大量的数据进行清洗、去重、标注…

Linux Centos7静默安装(非图形安装)Oracle RAC 11gR2(Oracle RAC 11.2.0.4)

Oracle RAC (全称Oracle Real Application Clusters &#xff09;静默安装&#xff08;非图形安装&#xff09;教程。 由于这篇文章花费了我太多时间&#xff0c;设置了仅粉丝可见&#xff0c;见谅。 环境说明&#xff1a; 虚拟机软件&#xff1a;VMware Workstation 16 Pro…

Git与VScode联合使用详解

目录 Git与VScode联合使用 方式一 1. 用vscode打开文件夹&#xff0c;如图点击初始化仓库&#xff0c;把此仓库初始为git仓库。 2. 提交文件到本地仓库 3. vscode与github账号绑定 4. 在github中建立远程仓库 5. 本地仓库与远程仓库绑定 方式二 1. 在github上建立远程仓…

VSCode添加Python解释器并安装Python库

目录 一、安装VSCode 二、安装Python解释器 1、安装包链接 2、安装过程 3、测试 4、安装flake8和yapf两个包 &#xff08;1&#xff09;安装flake8包 &#xff08;2&#xff09;安装yapf包 三、VSCode中选择python解释器 一、安装VSCode VSCode安装教程&#xff08;默…

Windows之任意文件删除到提权

前言 ZDI 发表过从任意文件夹删除到提权的利用过程&#xff0c;还提供了任意文件删除到提权的利用过程&#xff0c;所以一字之差但是漏洞利用方式也是有细微偏差的。 这里把任意文件删除和任意文件夹删除漏洞提权结合起来分析&#xff0c;是因为其最后的利用过程是一样的&…

Linux内核 - 同步机制之完成事件

背景 在复杂的软件系统中&#xff0c;常常存在多个并行运行的异步逻辑&#xff0c;然而&#xff0c;有些情况下&#xff0c;我们需要确保某些逻辑按照特定的时序顺序执行&#xff0c;以满足严格的时序要求。在这种情况下&#xff0c;我们可以使用同步机制&#xff0c;具体来说…

认识监控系统zabbix

利用一个优秀的监控软件&#xff0c;我们可以: ●通过一个友好的界面进行浏览整个网站所有的服务器状态 ●可以在 Web 前端方便的查看监控数据 ●可以回溯寻找事故发生时系统的问题和报警情况 了解zabbix zabbix是什么&#xff1f; ●zabbix 是一个基于 Web 界面的提供分布…

JVM:从零到入门

JVM&#xff0c;就是Java虚拟机。 JVM是一个巨大的话题&#xff0c;我们本文主要简单介绍一些围绕JVM相关的基础知识。 目录 JVM内存区域划分 本地方法栈 虚拟机栈 堆 程序计数器 方法区/ 元数据区 类加载 1.加载 2.验证 3.准备 4.解析 5.初始化 双亲委派模型 …

yydict属性字典-一种更加方便的方式访问字典

yydict属性字典-一种更加方便的方式访问字典 问题引入 这篇文章是想介绍 最近在使用字典的一种困惑. 我希望通过少写几个字符来访问 python中字典这种数据结构. 比如这个例子: person {name: frank,age: 18,hobby: swimming }在python中字典的定义 如上面的例子, 如果我希…

描述 power iteration(幂法)是啥?

幂法&#xff08;Power Iteration&#xff09;是一种迭代算法&#xff0c;用于计算一个矩阵的最大特征值和对应的特征向量。它是特征值求解问题中常用的一种方法。 幂法基于以下观察&#xff1a;如果一个矩阵 A 的某个特征向量 x 对应的特征值 λ 是最大的&#xff0c;那么当将…

spring boot mybatis plus mapper如何自动注册到spring bean容器

##Import(AutoConfiguredMapperScannerRegistrar.class) ##注册MapperScannerConfigurer ##MapperScannerConfigurer.postProcessBeanDefinitionRegistry方法扫描注册mapper ##找到mapper候选者 ##过滤mapper 类 候选者 ##BeanDefinitionHolder注册到spring 容器

vue项目之.env文件.env.dev、test、pro

.env文件是vue运行项目时的环境配置文件。 .env: 全局默认配置文件&#xff0c;所有环境(开发、测试、生产等&#xff09;均会加载并合并该文件 .env.development(开发环境默认命名) 开发环境的配置&#xff0c;文件名默认为.env.development,如果需要改名也是可以的&#xf…

安卓主板_MTK联发科低功耗迷你安卓核心板开发板定制开发

卓越V100安卓主板 是新移科技推出的4G物联网行业通用主板。卓越V100安卓主板基于 联发科MT6761安卓核心板设计&#xff0c;支持运行Android9.0 系统&#xff0c;通用性强&#xff0c;有很好的人机交互性&#xff0c;可进行二次开发&#xff0c;有良好的移植性。 另外&#xff…

面试经典150题(82-83)

leetcode 150道题 计划花两个月时候刷完&#xff0c;今天&#xff08;第四十一天&#xff09;完成了2道(82-83)150&#xff1a; 82.&#xff08;133. 克隆图&#xff09;题目描述&#xff1a; 给你无向 连通 图中一个节点的引用&#xff0c;请你返回该图的 深拷贝&#xff08…

ZZULIOJ 1118: 数列有序

题目描述 一个非递减有序的整型数组有n个元素&#xff0c;给定一个整数num&#xff0c;将num插入该序列的适当位置&#xff0c;使序列仍保持非递减有序。 要求定义一个函数insert()&#xff0c;将整数num插入在数组a的适当位置上&#xff0c;函数原型如下&#xff1a; void …

面向工业的复合自动机器学习

一、工业数据收集与处理 在面向工业的复合自动机器学习中&#xff0c;数据的收集和处理是至关重要的第一步。工业数据通常具有大规模、高维度和非线性的特点&#xff0c;需要运用先进的数据处理技术进行有效的管理和分析。这包括数据清洗、数据预处理、数据增强等一系列操作&a…

【Python】使用pyinstaller打包为Windows平台的xxx.exe方法步骤

pyinstaller 是一个用于将 Python 代码打包成独立可执行文件的工具&#xff0c;它可以将 Python 代码打包成 Windows、Linux、Mac 等平台的可执行文件&#xff0c;方便用户在不同环境中运行。 pyinstaller用法&#xff1a; 1.安装pyinstaller库&#xff0c;这里以PyCharm环境为…

ZZULIOJ 1113: 递归调用的次数统计(函数专题)

题目描述 如下程序的功能是计算 Fibonacci数列的第n项。函数fib()是一个递归函数。请你改写该程序&#xff0c;计算第n项的同时&#xff0c;统计调用了多少次函数fib&#xff08;包括main()对fib()的调用&#xff09;。 #include<stdio.h> int fib(int k); int main() {…