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_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    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();
}

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

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

相关文章

Windows如何安装go环境,离线安装beego

一、安装go 1、下载go All releases - The Go Programming Language 通过网盘分享的文件&#xff1a;分享的文件 链接: https://pan.baidu.com/s/1MCbo3k3otSoVdmIR4mpPiQ 提取码: hxgf 下载amd64.zip文件&#xff0c;然后解压到指定的路径 2、配置环境变量 需要新建两个环境…

AI Agent:重塑业务流程自动化的未来力量(2/30)

《AI Agent&#xff1a;重塑业务流程自动化的未来力量》 摘要&#xff1a;整体思路是先介绍 AI Agent 的基本情况&#xff0c;再深入阐述其实现业务流程自动化的方法和在不同领域的应用&#xff0c;接着分析其价值和面临的挑战&#xff0c;最后得出结论&#xff0c;为读者全面…

R语言的数据结构-矩阵

【图书推荐】《R语言医学数据分析实践》-CSDN博客 《R语言医学数据分析实践 李丹 宋立桓 蔡伟祺 清华大学出版社9787302673484》【摘要 书评 试读】- 京东图书 (jd.com) R语言医学数据分析实践-R语言的数据结构-CSDN博客 矩阵是一个二维数组&#xff0c;矩阵中的元素都具有相…

springboot+javafx使用aop切面导致的fx:id不能被注入问题

记录一个我遇到得问题 问题描述 我本来使用AOP切面来进行全局异常管理&#xff0c;但是使用AOP之后fxml中通过fx:id绑定得参数无法被注入 Slf4j Component Aspect public class GlobalExceptionAspect {AfterThrowing(pointcut "execution(* com.shkj.videoclassifica…

STM32 HAL库 + LM2904运算放大器 + ADC + 4-20ma液位传感器:电路设计及代码实现

4-20ma液位传感器在工业自动化和日常应用中非常常见&#xff0c;例如水位监测、液体储罐管理等。本文将结合STM32 HAL库&#xff0c;带你实现一个简单的液位监测demo&#xff0c;从电路设计到代码实现&#xff0c;实现通过单通道ADC采集4-20ma液位传感器的信号&#xff0c;并通…

MongoDB-固定集合(Capped Collection)

在 MongoDB 中&#xff0c;固定集合&#xff08;Capped Collection&#xff09;是一种具有特殊属性的集合。固定集合具有一个固定的最大大小&#xff0c;并且一旦达到该大小时&#xff0c;最早插入的文档将会被自动删除&#xff0c;以便为新的文档腾出空间。固定集合的这种特性…

Vue2 基础

Vue 2 是 Vue.js 的第二个主要版本&#xff0c;于 2016 年发布。它是一个渐进式的 JavaScript 框架&#xff0c;以其简单、灵活、易用性高而广受欢迎。Vue 2 主要专注于构建用户界面&#xff08;UI&#xff09;&#xff0c;并且非常适合用于构建单页应用&#xff08;SPA&#x…

2450.学习周刊-2024年50周

封面 人生五个球 ✍优秀博文 面对老板安排的工作&#xff0c;事事有回应&#xff0c;有必要吗&#xff1f; 职场精英进阶手册&#xff1a;工作推进五原则&#xff0c;让你合理高效地利用时间 上个班而已&#xff0c;千万别畏手畏脚 理解了雷军说的SU7要守正出奇&#xff0…

基于Llamaindex的网页内容爬取实战

目的 本文不关注如何解析网页 html 元素和各种 python 爬虫技术&#xff0c;仅作为一种网页数据的预处理手段进行研究。Llamaindex 也并不是爬虫技术的集大成者&#xff0c;使用它是为了后续的存查一体化。 安装依赖 pip install llama-index-readers-web # pip install llam…

Excel拆分脚本

Excel拆分 工作表按行拆分为工作薄 工作表按行拆分为工作薄 打开要拆分的Excel文件&#xff0c;使用快捷键&#xff08;AltF11&#xff09;打开脚本界面&#xff0c;选择要拆分的sheet&#xff0c;打开Module&#xff0c;在Module中输入脚本代码&#xff0c;然后运行脚本 Su…

go语言zero项目通过Supervisor启动与停用的管理

为了让Go项目通过 Supervisor 启动与重启&#xff0c;您需要确保已经正确安装和配置了 Supervisor。接下来是详细的步骤来配置您的 Go 项目&#xff0c;使其可以通过 Supervisor 管理。 ### 配置 Go 项目 首先&#xff0c;确保您的 Go 项目可以编译成一个可执行文件&#xff…

【ABAP SAP】开发-BUG修补记录_采购申请打印时品名规格品牌为空

项目场景&#xff1a; TCODE:自开发程序ZMMF004 采购申请打印 问题描述 ZMMF004打印的时候&#xff0c;有的采购申请的品名、规格、品牌为空 原因分析&#xff1a; 1、首先我通过写SQL语句查底表来看这几条采购申请本身有无品名、规格、品牌 SQL语句如下&#xff0c;只需修…

汽车租赁系统数据库 E-R 图设计

文章目录 汽车租赁系统数据库 E-R 图设计一、实体&#xff08;Entities&#xff09;二、实体间关系&#xff08;Relationships&#xff09;三、数据表&#xff08;Tables&#xff09; 汽车租赁系统数据库 E-R 图设计 一、实体&#xff08;Entities&#xff09; 用户&#xff0…

【小沐学GIS】基于C++绘制三维数字地球Earth(OpenGL、glfw、glut、QT)第三期

&#x1f37a;三维数字地球系列相关文章如下&#x1f37a;&#xff1a;1【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;456:OpenGL、glfw、glut&#xff09;第一期2【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;456:OpenGL、glfw、glut&#xff09;第二期3【小沐…

Vizcom:AI驱动的草图到3D设计革命

Vizcom是一家领先的AI技术公司,专注于为工业设计师提供工具,将手绘草图快速转化为可制造的3D模型,从而加速产品迭代和创新。 公司背景与愿景 成立于2021年的Vizcom由前Nvidia工业设计师Jordan Taylor创立。Taylor凭借其深厚的创意设计背景和技术敏锐度,看到了生成对抗网络…

【开源免费】基于SpringBoot+Vue.JS课程智能组卷系统(JAVA毕业设计)

本文项目编号 T 009 &#xff0c;文末自助获取源码 \color{red}{T009&#xff0c;文末自助获取源码} T009&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 老…

Linux常用指令-----下

Linux常用指令------上 Linux常用指令------中 Linux系列 文章目录 Linux系列前言一、more指令二、less指令三、head指令和tail指令四、grep指令五、zip指令和unzip指令六、tar指令1、打包压缩2. 预览3. 解压解包 前言 在上一篇博客中&#xff0c;我給大家介绍了cat指令&#…

【安全研究】某黑产网站后台滲透与逆向分析

文章目录 x01. 前言x02. 分析 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与…

【Linux SH脚本】LinuxCheck 应急检查信息脚本

LinuxCheck 1.下载地址 【Linux SH脚本】LinuxCheck 应急检查信息脚本 2.简介 LinuxCheck 是一个开源的自动化检查脚本&#xff0c;旨在快速检测 Linux 系统的安全配置和潜在问题。它支持多种发行版&#xff0c;能够扫描并生成详细的报告&#xff0c;涵盖用户管理、权限配置…

JaxaFx学习(一)

目录&#xff1a; &#xff08;1&#xff09;基本结构 &#xff08;2&#xff09;Application &#xff08;3&#xff09;Stage窗口显示 &#xff08;4&#xff09;Scene场景切换 &#xff08;5&#xff09;UI控件通用属性 &#xff08;6&#xff09;UI控件属性绑定很属性…