QT:Widgets中的事件

事件的处理

(1)重新实现部件的paintEvent()、mousePressEvent()等事件处理函数。这是最常用的一种方法,不过它只能用来处理特定部件的特定事件。
(2)重新实现notify()函数。这个函数功能强大,提供了完全的控制,可以在事件过滤器得到事件之前就获得它们。但是,它一次只能处理一个事件。需要继承自QApplication类
(3)向QApplication对象上安装事件过滤器。因为一个程序只有一个QApplication对象,所以这样实现的功能与使用notify()函数是相同的,优点是可以同时处理多个事件。需要继承自QApplication类
(4)重新实现event()函数。QObject类的event()函数可以在事件到达默认的事件处理函数之前获得该事件。
(5)在对象上安装事件过滤器。使用事件过滤器可以在一个界面类中同时处理不同子部件的不同事件。

事件的传递

在这里插入图片描述
在这里插入图片描述
新建C++类
在这里插入图片描述
在这里插入图片描述
将mylineedit.h文件内容修改如下

#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H
#include <QDebug>
#include <QLineEdit>
#include <QWidget>
class MyLineEdit : public QLineEdit
{Q_OBJECT
public:explicit MyLineEdit(QWidget *parent = nullptr);
protected:void keyPressEvent(QKeyEvent *event) override;};#endif // MYLINEEDIT_H

mylineedit.cpp文件修改为如下所示

#include "mylineedit.h"
#include <QKeyEvent>
#include <QDebug>
#include <QWidget>MyLineEdit::MyLineEdit(QWidget *parent):QLineEdit(parent)
{}void MyLineEdit::keyPressEvent(QKeyEvent *event)
{qDebug() << tr("MyLineEdit::keyPressEvent");
}

widget.h文件,添加类前置声明:

class MyLineEdit;

添加函数声明:

protected:void keyPressEvent(QKeyEvent *event) override;

添加一个private对象指针:

    MyLineEdit *lineEdit;

在Widget类的构造函数中添加代码:

    lineEdit = new MyLineEdit(this);lineEdit->move(100,100);

添加事件处理函数的定义:

void Widget::keyPressEvent(QKeyEvent *event)
{Q_UNUSED(event);qDebug() << tr("Widget::keyPressEvent");}

这里自定义了一个MyLineEdit类,它继承自QLineEdit类,然后在Widget界面中添加了一个MyLineEdit部件。

现在运行程序,这时光标焦点在行编辑器中,随便在键盘上按一个按键,比如按下A键,则Qt Creator的应用程序输出栏中只会出现“"MyLineEdit::keyPressEvent”​,

到mylineedit.cpp文件中的keyPressEvent()函数最后添加如下一行代码,让它忽略掉这个事件。

void MyLineEdit::keyPressEvent(QKeyEvent *event)
{qDebug() << tr("MyLineEdit::keyPressEvent");QLineEdit::keyPressEvent(event);}

再运行程序,按下A键,那么在以前输出的基础上又输出了“"Widget::keyPressEvent”​,

但是现在出现了一个问题,就是行编辑器中无法输入任何字符,为了让它可以正常工作,用户还需要在mylineedit.cpp文件的keyPressEvent()函数中添加一行代码,

void MyLineEdit::keyPressEvent(QKeyEvent *event)
{qDebug() << tr("MyLineEdit::keyPressEvent");QLineEdit::keyPressEvent(event);event->ignore();
}

这里调用了MyLineEdit父类QLineEdit的keyPressEvent()函数来实现行编辑器的默认操作。这里一定要注意代码的顺序,ignore()函数要在最后调用。

总结

在这里,我们通过调用父类 QLineEdit 的 keyPressEvent() 函数来实现行编辑器的默认操作。特别需要注意的是,调用 ignore() 函数来忽略当前事件处理的顺序至关重要,并且应该在最后执行。这样可以确保先执行完父类的默认行为,然后再决定是否忽略当前事件。

使用事件过滤器

在mylineedit.h文件中添加public函数声明:

bool event(QEvent *event) override;

在mylineedit.cpp文件中对该函数进行定义:

void MyLineEdit::event(QKeyEvent *event)
{if(event->type() == QEvent::KeyPress){qDebug() << tr("MyLineEdit::event");}return QLineEdit::event(event);
}

进入widget.h文件中进行public函数的声明:

 bool eventFilter(QObject *obj,QEvent *event) override;

到widget.cpp文件中,在构造函数的最后添上一行代码:

lineEdit->installEventFilter(this);

添加事件过滤器函数的定义:

bool  Widget::eventFilter(QObject *obj,QEvent *event)
{if(obj == lineEdit){if(event->type() == QEvent::KeyPress){qDebug() << tr("Widget:eventFilte");}}return QWidget::eventFilter(obj,event);
}

在事件过滤器中,先判断该事件的对象是不是lineEdit,如果是,再判断事件类型。最后返回了QWidget类默认的事件过滤器的执行结果。
在这里插入图片描述
首先是widget的过滤事件被执行,
然后是MyLineEdit的事件keyPressEvent
接着是MyLineEdit 的
最后是Widget的keyPressEvent

需要注意,event()函数和事件处理函数是在焦点部件内进行重新定义的,而事件过滤器却是在焦点部件的父部件中进行定义的。

代码

mylineedit.h

#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H
#include <QDebug>
#include <QLineEdit>
#include <QWidget>
#include <QEvent>
class MyLineEdit : public QLineEdit
{Q_OBJECT
public:explicit MyLineEdit(QWidget *parent = nullptr);bool event(QEvent *event) override;
protected:void keyPressEvent(QKeyEvent *event) override;};#endif // MYLINEEDIT_H

mylineedit.cpp

#include "mylineedit.h"
#include <QKeyEvent>
#include <QDebug>
#include <QWidget>MyLineEdit::MyLineEdit(QWidget *parent):QLineEdit(parent)
{}
void MyLineEdit::keyPressEvent(QKeyEvent *event)
{qDebug() << tr("MyLineEdit::keyPressEvent");QLineEdit::keyPressEvent(event);event->ignore();
}
bool MyLineEdit::event(QEvent *event)
{if(event->type() == QEvent::KeyPress){qDebug() << tr("MyLineEdit::event");}return QLineEdit::event(event);
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;QPointF offset;//用来存储鼠标指针位置与窗口位置的差值//添加声明
protected:void mousePressEvent(QMouseEvent *event) override;//鼠标按下事件void mouseReleaseEvent(QMouseEvent *event) override;//void mouseDoubleClickEvent(QMouseEvent *event) override;//鼠标双击事件void mouseMoveEvent(QMouseEvent *event) override;//鼠标移动事件void wheelEvent(QWheelEvent *event) override;//滚轮事件void keyPressEvent(QKeyEvent *event) override;void keyReleaseEvent(QKeyEvent *event) override;};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QMouseEvent>
#include<QDebug>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QCursor cursor;//创建光标对象cursor.setShape(Qt::OpenHandCursor);//设置光标的形状setCursor(cursor);//使用光标// setMouseTracking(true);//不按鼠标按键,也可以获取鼠标移动事件,那么就要在构造函数中添加下面一行代码:
}Widget::~Widget()
{delete ui;
}void Widget::mousePressEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){QCursor cursor;cursor.setShape(Qt::ClosedHandCursor);QApplication::setOverrideCursor(cursor);//使用鼠标指针暂时改变形状offset = event->globalPosition() - pos();// qDebug()<< "event->globalPosition()" <<  event->globalPosition();// qDebug()<< "pos()" << pos();// qDebug()<< "offset" << offset;/**event->globalPosition():*返回的是鼠标在整个屏幕坐标系下的当前位置坐标*pos():*返回的是该部件在其父部件(或者整个窗口系统层级中相应的参照位置)中的相对位置坐标*
*/}else if(event->button() == Qt::RightButton){//按下鼠标右键时鼠标光标显示的是自定义的图片//注意:这里的路径实在build目录下寻找QCursor cursor(QPixmap("../../mymouseevent/logo.png"));QApplication::setOverrideCursor(cursor);}}void Widget::mouseReleaseEvent(QMouseEvent *event)
{Q_UNUSED(event);QApplication::restoreOverrideCursor();//释放鼠标后,鼠标恢复为原状}void Widget::mouseDoubleClickEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){if(windowState() != Qt::WindowFullScreen){setWindowState(Qt::WindowFullScreen);//设置为全屏}else{setWindowState(Qt::WindowNoState);//恢复之前大小}}}void Widget::mouseMoveEvent(QMouseEvent *event)
{if(event->buttons() & Qt::LeftButton){QPointF temp;temp = event->globalPosition() - offset;// qDebug()<< "event->globalPosition()" <<  event->globalPosition();// qDebug()<< "offset" << offset;move(temp.x(),temp.y());}}void Widget::wheelEvent(QWheelEvent *event)
{int i =event->angleDelta().y();qDebug()<< "angleDelta().y()" << i;if(event->angleDelta().y() > 0){ui->textEdit->zoomIn();//进行放大}else{ui->textEdit->zoomOut();//进行缩小}}void Widget::keyPressEvent(QKeyEvent *event)
{//如果确定按下了 Ctrl 键(即 event->modifiers() == Qt::ControlModifier 条件成立)if(event->modifiers() == Qt::ControlModifier){if(event->key() == Qt::Key_M){qDebug()<< "Qt::Key_M" ;}else if(event->key() == Qt::Key_A){qDebug()<< "Qt::Key_A" ;}}else{if (event->key() >= Qt::Key_1 && event->key() <= Qt::Key_9){qDebug() << "单独按下数字键: " << event->key();}}}void Widget::keyReleaseEvent(QKeyEvent *event)
{}

可以在界面上按住鼠标左键来拖动窗口,双击鼠标左键来使其全屏,按住鼠标右键则使指针变为一个自定义的图片,而使用滚轮可以放大或者缩小编辑器中的内容。

main.cpp

#include "widget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

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

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

相关文章

jvm结构介绍

Java虚拟机&#xff08;JVM&#xff09;是Java平台的核心组件&#xff0c;它负责将Java字节码转换为机器码 1. 类加载子系统&#xff08;Class Loading Subsystem&#xff09;&#xff1a; • 负责将Java类加载到JVM中。这包括从文件系统、网络或其他来源读取.class文件&#x…

uni-app多环境配置动态修改

前言 这篇文章主要介绍uniapp在Hbuilderx 中&#xff0c;通过工程化&#xff0c;区分不同环境、动态修改小程序appid以及自定义条件编译&#xff0c;解决代码发布和运行时手动切换问题。 背景 当我们使用uniapp开发同一个项目发布不同的环境二级路径不同时&#xff0c;这时候…

antdv-<a-button>中属性的使用

UI组件库&#xff08;User Interface Component Library&#xff09;是一种预先构建好的、可重用的用户界面元素集合&#xff0c;旨在帮助开发者更快速、更简便地构建用户界面。这些组件通常包括按钮、表单、导航栏、模态框等&#xff0c;能够提供一致的外观和交互风格&#xf…

解决“VMware虚拟机报Intel VT-x”错误

今天&#xff0c;在windows系统上&#xff0c;打开VMware WorkStation v15软件里的虚拟机&#xff0c;弹出"Intel VT-x处于禁用状态"错误&#xff0c;如图(1)所示&#xff1a; 图(1) 虚拟机报"Intel VT-x"错误 问题原因&#xff1a;当前电脑的BIOS没有开启…

【Linux-ubuntu通过USB传输程序点亮LED灯】

Linux-ubuntu通过USB传输程序点亮LED灯 一,初始化GPIO配置1.使能时钟2.其他寄存器配置 二&#xff0c;程序编译三&#xff0c;USB传输程序 一,初始化GPIO配置 1.使能时钟 使能就是一个控制信号&#xff0c;用于决定时钟信号是否能够有效的传递或者被使用&#xff0c;就像一个…

2024首届世界酒中国菜国际地理标志产品美食文化节成功举办篇章

2024首届世界酒中国菜国际地理标志产品美食文化节成功举办&#xff0c;开启美食文化交流新篇章 近日&#xff0c;首届世界酒中国菜国际地理标志产品美食文化节在中国国际地理标志大厦成功举办&#xff0c;这场为期三天的美食文化盛会吸引了来自世界各地的美食爱好者、行业专家…

vue运行项目时local有显示 但是network却显示unavailable

问题描述 日常开发中 和后端本地调试时 后端需要使用你的本地去访问页面 可运行项目时会出现network显示unavailable的情况 解决方式 1.其实这只是vue脚手架对于ip地址获取的方式兼容上有一些问题 但其实是不影响ip访问本地的 你可以直接cmd内ipconfig去查看自己的ip然后…

Edge SCDN的独特优势有哪些?

强大的边缘计算能力 Edge SCDN&#xff08;边缘安全加速&#xff09;是酷盾安全推出的边缘集分布式 DDoS 防护、CC 防护、WAF 防护、BOT 行为分析为一体的安全加速解决方案。通过边缘缓存技术&#xff0c;智能调度使用户就近获取所需内容&#xff0c;为用户提供稳定快速的访问…

【SpringAOP】深入浅出SpringAOP从原理到源码

AOP对象是如何创建的 对于熟悉Spring IOC流程源码的同学来说&#xff0c;一定了解bean的整个生命周期&#xff0c;也就是从实例化、属性填充、初始化三个过程。那么对于Bean 工厂来说&#xff0c;是如何保证需要创建代理的对象创建代理的呢。 从图中可以看到&#xff0c;本质…

【Go】Linux、Windows、Mac 搭建Go开发环境

1、Linux 第一步&#xff0c;在 官网 下包&#xff0c;如 go1.23.4.linux-386.tar.gz&#xff08;注意架构区分&#xff09; 第二步&#xff0c;将包上传至服务器&#xff0c;假如上传到 tmp目录下第三步&#xff0c;安装# 解压 tar -C /app -xzvf go1.23.4.linux-386.tar.gz#…

电子科技大学考研,计算机与软件专业怎么选择?

电子科技大学在计算机与软件领域具备卓越实力&#xff0c;其毕业生就业前景及薪资水平均颇为可观。因此&#xff0c;学生应依据个人课程专长来选定专业。若各项课程均表现出色&#xff0c;推荐25届考生优先考虑软件专业&#xff0c;因其上岸难度相对较低。 接下来&#xff0c;C…

Unity3D实现抽象类的应用场景例子

系列文章目录 unity知识点 文章目录 系列文章目录👉前言👉一、示例👉二、使用步骤👉三、抽象类和接口的区别👉3-1、抽象类👉3-2、接口类👉壁纸分享👉总结👉前言 假设我们正在制作一个游戏,游戏中有多种不同类型的角色,这些角色都有一些共同的行为(比如移…

(五)机器学习 - 数据分布

数据分布&#xff08;Data Distribution&#xff09;是指数据在不同值或值区间内的分布情况&#xff0c;它描述了数据点在整个数据集中是如何分散或集中的。数据分布可以通过多种方式来分析和表示&#xff0c;包括图形和数值方法。 常见的数据分布特征和描述数据分布的方法&…

【恶意软件检测论文】用于 Android 恶意软件检测的混合 ML-DL 方法

目录 摘要1. 引言2. 文献综述传统检测方法机器学习方法混合方法最新进展移动恶意软件检测的挑战 3. 问题陈述4. 研究目标5. 提出的方法论1. 数据集获取2. 数据预处理3. 特征工程和选择4. 模型实现5. 模型评估6. 比较和分析 6. 结论 用于 Android 恶意软件检测的混合 ML-DL 方法…

Linux网络 UDP socket

背景知识 我们知道&#xff0c; IP 地址用来标识互联网中唯一的一台主机&#xff0c; port 用来标识该主机上唯一的一个网络进程&#xff0c;IPPort 就能表示互联网中唯一的一个进程。所以通信的时候&#xff0c;本质是两个互联网进程代表人来进行通信&#xff0c;{srcIp&…

STM32F407+LAN8720A +LWIP +FreeRTOS UDP通讯

STM32F407+LAN8720A +LWIP +FreeRTOS ping通 上一篇实现了LWIP ping 通 本篇实现UDP通讯 实现如下功能: 串口1空闲中断+DMA接收,收到数据用UDP发送UDP接收,收到数据用串口1发送STM32CUBEIDE配置和代码 1. 配置UARAT1的空闲中断+DMA接收 UART1接收到数据,释放信号量,在任…

Git-基础操作命令

目录 Git基础操作命令 case *查看提交日志 log 版本回退 get add . Git基础操作命令 我们创建并且初始化这个仓库以后&#xff0c;我们就要在里面进行操作。 Git 对于文件的增删改查存在几个状态&#xff0c;这些修改状态会随着我们执行Git的命令而发生变化。 untracked、…

简单的Java_Swing小项目

Swing小项目 无需任何额外配置&#xff0c;直接可以在eclipse用 非常简单的文件结构 简单的登录界面 进去后就大概是这么个样子 很久以前写的了&#xff0c;我就不一一打开展示了。内容和无UI版本差不多&#xff0c;只是用简单的Swing实现了界面化操作 数据是可以保存在…

回归任务与分类任务应用及评价指标

能源系统中的回归任务与分类任务应用及评价指标 一、回归任务应用1.1 能源系统中的回归任务应用1.1.1 能源消耗预测1.1.2 负荷预测1.1.3 电池健康状态估计&#xff08;SOH预测&#xff09;1.1.4 太阳能发电量预测1.1.5 风能发电量预测 1.2 回归任务中的评价指标1.2.1 RMSE&…

嵌入式学习(18)-stm32F407串口接收空闲中断+DMA

一、概述 在一些一次性接收大批量数据的引用场合&#xff0c;如果使用接收中断会频繁的进入接收中断影响代码的运行效率。为了解决这个问题可以使用串口的空闲中断DMA实现。 二、应用 在网上招了一些例程在STM32F407的平台上都没有跑通会出现各种异常&#xff0c;主要原因还…