【Qt开发流程】之事件过滤器及sendEvent和postEvent

描述

事件过滤器(Event Filter)是Qt中一个强大的事件处理机制,它可以在对象接收到事件之前截获事件,并进行自定义处理。事件过滤器可以在不修改对象自身代码的前提下,对其进行事件处理和拦截。

事件过滤器的使用过程如下:

  1. 创建一个QObject对象,为其安装事件过滤器。

  2. 重载事件过滤器的eventFilter函数,实现自定义的事件拦截和处理。

  3. 在需要拦截和处理事件的对象上,调用installEventFilter函数,将事件过滤器安装到该对象上。

  4. 在事件过滤器中实现自定义事件处理逻辑。

  5. 在事件过滤器的eventFilter函数中,调用QObject::eventFilter()函数,将事件传递给下一个事件接收器,事件接收器可以是该对象本身或者其父对象。

使用事件过滤器可以对QWidgetQApplicationQCoreApplication等对象进行事件处理,常用于实现自定义事件处理逻辑、事件日志等。

示例

以下是用于拦截并处理QLineEdit对象的按键事件,实现只能输入数字:

#include <QDebug>
#include <QObject>
#include <QLineEdit>
#include <QKeyEvent>
#include <QRegExp>

class DigitFilter : public QObject
{
    Q_OBJECT
public:
    explicit DigitFilter(QObject *parent = nullptr) : QObject(parent){
        m_regExp.setPattern("[a-zA-Z0-9]+$");
    }

    bool eventFilter(QObject *obj, QEvent *event) override
    {
        qDebug().noquote() << "[" << __FILE__ << __LINE__ << "]" <<  event->type();
        if(event->type() == QEvent::KeyPress) {
            QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
            if(isDigit(keyEvent->text().at(0)) && m_regExp.exactMatch(keyEvent->text()))
                return false;
            else
                return true;
        }else {
            return QObject::eventFilter(obj, event);
        }
    }

private:
    bool isDigit(const QChar &c)
    {
        return c >= QLatin1Char('0') && c <= QLatin1Char('9');
    }

private:
    QRegExp m_regExp;
};

// main.cpp
#include <QApplication>
#include <QLineEdit>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QLineEdit lineEdit;
    DigitFilter digitFilter;
    lineEdit.installEventFilter(&digitFilter);

    lineEdit.show();

    return a.exec();
}

以上代码作用:

  • 在上述代码中,新建了一个名为DigitFilter的QObject子类,该类继承QObject类并重载了eventFilter函数,该函数用于拦截QLineEdit对象的按键事件,并判断该事件传递的按键是否为数字,如果是则返回false,否则返回true。
  • 使用installEventFilter函数将该事件过滤器安装到QLineEdit对象上,从而实现只能输入数字的功能。

sendEvent()

bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event);

使用notify()函数将事件事件直接发送给接收者。返回从事件处理程序返回的值。
事件发送后不会被删除。通常的方法是在堆栈上创建事件,例如:

	QMouseEvent event(QEvent::MouseButtonPress, pos, 0, 0, 0);
    QApplication::sendEvent(mainWindow, &event);

postEvent()

void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority)

将事件事件(以对象接收者作为事件接收者)添加到事件队列并立即返回。
事件必须在堆上分配,因为post事件队列将获得事件的所有权,并在事件被发布后将其删除。在事件发布之后再访问它是不安全的。
当控制返回到主事件循环时,存储在队列中的所有事件都将使用notify()函数发送。
事件按优先级降序排序,即高优先级事件排在低优先级事件之前。优先级可以是任何整数值,即在INT_MAX和INT_MIN之间,包括;更多细节可以参考Qt::EventPriority。具有同等优先级的事件将按发布的顺序处理。
注意:这个函数是线程安全的。

示例

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QEvent>

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

    //ui->lineEdit->installEventFilter(new DigitFilter);

    ui->spinBox->installEventFilter(this);
    ui->spinBox->setFocus();
    QKeyEvent e(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);
    QApplication::sendEvent(ui->spinBox, &e);
}

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

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == ui->spinBox)
    {
        if(event->type() == QEvent::KeyPress)
        {
            QKeyEvent* e = static_cast<QKeyEvent*>(event);
            if(e->key() == Qt::Key_Space)
            {
                ui->spinBox->setValue(0);
                return true;
            }else {
                return false;
            }
        }else {
            return false;
        }
    }else {
        return QMainWindow::eventFilter(watched, event);
    }
}

运行后,spinBox控件的值变为了1.
在这里插入图片描述

结论

万事开头难,然后中间难,最后结尾难

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

10、SQL注入——数据库基础

文章目录 一、数据库概述二、数据库分类Mysql数据库连接方法 三、识别数据库四、SQL语法4.1 SQL基本语法4.2 高级操作 一、数据库概述 数据库&#xff08;database&#xff09;&#xff1a;存储在磁盘、磁带、光盘或其他外存介质上、按一定结构组织在一起的相关数据的集合。数…

QML学习一、GridView的使用和增加添加动画、删除动画

一、效果预览 二、源码分享 import QtQuick import QtQuick.ControlsApplicationWindow {visible: truewidth: 640height: 480title: "Test"property int cnt:cnt model.countListModel{id:modelListElement{index:0}ListElement{index:1}ListElement{index:2}List…

EM32DX-C2【C#】

1说明&#xff1a; 分布式io&#xff0c;CAN总线&#xff0c;C#上位机二次开发&#xff08;usb转CAN模块&#xff09; 2DI&#xff1a; 公共端是&#xff1a; 0V【GND】 X0~X15&#xff1a;自带24v 寄存器地址&#xff1a;0x6100-01 6100H DI输入寄存器 16-bit &#x…

MX6ULL学习笔记 (七) 中断实验

前言&#xff1a; 本章我们就来学习一 下如何在 Linux 下使用中断。在linux内核里面使用中断&#xff0c;不同于我们以往在别的裸机开发一样&#xff0c;需要进行各种寄存器的配置&#xff0c;中断使能之类的&#xff0c;而在Linux 内核中&#xff0c;提供了完善的中断框架…

vue项目配置多个代理

在本地.env文件配置本地/测试/预发/正式 路径&#xff1a; 在vue.config.js 里面配置&#xff1a; module.exports defineConfig({transpileDependencies: false,lintOnSave: false,outputDir: process.env.VUE_APP_DIST,publicPath: /,css: {loaderOptions: {postcss: {// p…

UNDERSTANDING AND IMPROVING INFORMATION TRANSFER IN MULTI-TASK LEARNING

Z i _i i​ X i R i X_iR_i Xi​Ri​&#xff0c; X X X是Task embedding layers&#xff0c; R R R是Alignment matrices 辅助信息 作者未提供代码

链表【3】

文章目录 &#x1f433;23. 合并 K 个升序链表&#x1f41f;题目&#x1f42c;算法原理&#x1f420;代码实现 &#x1f437;25. K 个一组翻转链表&#x1f416;题目&#x1f43d;算法原理&#x1f367;代码实现 &#x1f433;23. 合并 K 个升序链表 &#x1f41f;题目 题目链…

C语言 操作符详解

C语言学习 目录 文章目录 前言 一、算术操作符 二、移位操作符 2.1 左移操作符 2.2 右移操作符 三、位操作符 3.1 按位与操作符 & 3.2 按位或操作符 | 3.3 按位异或操作符 ^ 四、赋值操作符 五、单目操作符 5.1 逻辑反操作符&#xff01; 5.2 正值、负值-操作符 5.3 取地址…

【Spring Boot】如何集成mybatis-plus

在pom文件中导入maven坐标 <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.23</version></dependency><!--mybatis-plus--><dependency><groupId>com.ba…

OpenResty(nginx+lua+resty-http)实现访问鉴权

OpenResty(nginxluaresty-http)实现访问鉴权 最近用BI框架解决了一些报表需求并生成了公开链接&#xff0c;现在CMS开发人员打算将其嵌入到业务系统中&#xff0c;结果发现公开链接一旦泄露任何人都可以访问&#xff0c;需要实现BI系统报表与业务系统同步的权限控制。但是目前…

软件测试【理论基础】

软件测试的IEEE定义&#xff1a;使用人工或自动的手段来运行或测量软件系统的过程&#xff0c;目的是检验软件系统是否满足规定的需求&#xff0c;并找出与预期结果之间的差异。 软件测试的发展趋势&#xff1a; ① 测试工作将进一步前移。软件测试不仅仅是单元测试、集成测…

Java中三种定时任务总结(schedule,quartz,xxl-job)

目录 1、Spring框架的定时任务 2、Quartz Quartz的用法 3、xxl-job 3.1 docker 安装xxl-job 3.2 xxl-job编程测试 补充&#xff1a;Java中自带的定时任务调度 1. java.util.Timer和java.util.TimerTask 2. java.util.concurrent.Executors和java.util.concurrent.Sche…

前端开发_CSS

CSS定义 层叠样式表 (Cascading Style Sheets&#xff0c;缩写为 CSS&#xff09;&#xff0c;是一种 样式表 语言&#xff0c;用来描述 HTML 文档的呈现&#xff08;美化内容&#xff09; 书写位置&#xff1a;title 标签下方添加 style 双标签&#xff0c;style 标签里面书…

Qt应用开发(Quick篇)——矩形模块 Rectangle

一、前言 矩形模块用于用纯色或渐变填充区域&#xff0c;或者提供一个矩形边框。 二、外观 每个矩形项都可以使用使用color属性指定的纯填充色、使用gradient类型定义并使用gradient属性设置的渐变来绘制。如果同时指定了颜色和渐变效果&#xff0c;则只会生效渐变效果。 通过…

探讨Unity中的动画融合技术(BlendTree)

动画在游戏和虚拟现实应用中扮演着关键的角色&#xff0c;而动画融合技术则是使角色动作更加流畅和逼真的核心。在Unity引擎中&#xff0c;我们可以使用动画混合树&#xff08;Blend Trees&#xff09;来实现这一目标。本篇技术博客将深入讨论动画融合技术的实现原理、在Unity中…

jsp前端输入中文数据传到controller变成问号?的解决办法

还是写老师布置的实验的时候&#xff0c;解决了xml文件找不到的问题之后又遇到新的问题&#xff1a;前端登录处输入用户名和密码&#xff0c;结果明明输入的用户名是对的密码也是对的&#xff08;输入的用户名是中文&#xff09;&#xff0c;它就是显示用户名或密码错误。然后我…

高压配电室智能运维

高压配电室智能运维是指通过运用先进的物联网、大数据、云计算等技术&#xff0c;对高压配电室进行智能化、远程化的运行维护&#xff0c;实现高压配电室的安全、高效、经济运行。以下是高压配电室智能运维的主要功能和优势&#xff1a; 实时监测&#xff1a;通过传感器和监测设…

Vue3引入markdown编辑器--Bytemd

字节跳动开源了一款markdown编辑器&#xff0c;bytemd&#xff0c;项目地址&#xff1a;GitHub - bytedance/bytemd: ByteMD v1 repository 安装 npm i bytemd/vue-next 引入方式如下&#xff0c;再main.js中引入样式 import bytemd/dist/index.css 直接封装一个Markdown编…

JavaEE进阶学习:SpringBoot 的创建和使用

1.什么是Spring Boot Spring 的诞生是为了简化 Java 程序的开发的&#xff0c;而 Spring Boot 的诞生是为了简化 Spring 程序开发的。 Spring Boot 翻译一下就是 Spring 脚手架&#xff0c;它就是为了快速开发 Spring 框架而诞生的 2.Spring Boot 优点 起步依赖 (创建的时候…

深入浅出理解kafka

1.Kafka简介 Kafka 本质上是一个 MQ&#xff08;Message Queue&#xff09;&#xff0c;使用消息队列的优点&#xff1a; 解耦&#xff1a;允许独立的扩展或修改队列两边的处理过程。可恢复性&#xff1a;即使一个处理消息的进程挂掉&#xff0c;加入队列中的消息仍然可以在系…