自学内容网 自学内容网

QT--事件(丰富操作,高级功能)

一、事件

1.事件与信号的区别
  • 事件来自外部,是随机发生的。信号来自内部,是主动发生的。有点像外中断和内中断的区别。
  • 事件:适用于处理系统级别的输入和状态变化,种类繁多,能够应对复杂的交互需求。
  • 信号/槽:适用于对象间通信和状态变化响应,灵活性高,支持异步通信和多线程编程。
  • 信号是单调的,而事件是丰富的。
2.事件系统QEvent
  • GUI(Graphical User Interface) 应用程序是由事件(event)驱动的,点击鼠标、按下某个按键、改变窗口大小、最小化窗口等都会产生相应的事件,应用程序对这些事件进行相应的处理以实现程序的功能。
  • 在大多数情况下,GUI进程和UI进程这两个术语是可以互换使用的,它们通常指的是同一个概念,即处理和管理图形用户界面(Graphical User Interface, GUI)以及用户与应用程序交互的进程。
  • 代码详解
#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
//QApplication类是Qt应用程序的核心,负责管理应用程序的控制流和主要设置。
通过构造函数QApplication::QApplication(int &argc, char **argv)创建
一个QApplication对象。这个对象初始化应用程序的环境,并且启动事件循环。


    Widget w;
    w.show();
//Widget w;创建一个名为w的Widget对象(假设Widget是自定义的窗口类,继承自QWidget或其子类)。
w.show();调用QWidget的show()方法,使窗口显示在屏幕上。显示窗口后,QWidget开始接收和处理事件。



    return a.exec();
 //a.exec()启动Qt的主事件循环。这是一个阻塞调用,直到应用程序退出(通常是通过调用QApplication::quit()或窗口关闭事件)。
在事件循环中,QApplication会持续监控事件队列,等待并处理各种事件,如鼠标点击、键盘输入、窗口重绘请求等。
}

3. 事件过滤器
  • 事件过滤器。它可以将一个对象的事件委托给另一个对象来监视并处理。例如,一个窗口可以作为其界面上的QLabel组件的事件过滤器,派发给QLabel 组件的事件由窗口去处理,这样,就不需要为了处理某种事件而新定义一个标签类。
  • 要实现事件过滤器功能,需要完成两项操作。
    - 被监视对象使用函数installEventFilter()将自己注册给监视对象,监视对象就是事件过滤器。
    - 监视对象重新实现函数eventFilter(),对监视到的事件进行处理。作为事件过滤器的监视对象需要重新实现函数eventFilter()
  • 事件过滤器可以在事件到达目标对象之前进行预处理,从而提供了更多的控制和灵活性。
  • 主要作用和使用场景
    1. 事件拦截和预处理
    - 检查修改事件:在事件到达目标对象之前检查和修改事件。例如,可以在事件到达目标对象之前记录事件信息、修改事件数据或阻止事件的进一步传播。
    - 实现自定义逻辑:在事件到达目标对象之前实现自定义逻辑。例如,可以在鼠标点击之前判断是否允许特定操作,或者在键盘输入之前进行输入验证。
    2. 统一处理多个对象的事件
    - 事件过滤器允许你统一处理多个对象的事件,而不需要在每个对象上实现事件处理函数。这对于管理复杂界面中的多个控件特别有用。
    - 集中处理事件:将事件处理逻辑集中到一个地方(即事件过滤器),而不是在每个控件的事件处理函数中实现。
    - 简化代码:减少代码重复,使代码更清晰、易于维护。
    3. 实现复杂的事件处理逻辑
    - 拦截阻止事件:根据需要阻止事件的进一步传播。例如,可以阻止鼠标事件在控件之间传播,或者阻止特定的键盘输入。
    - 实现全局事件处理:在整个应用程序中实现全局事件处理逻辑,例如处理所有控件的鼠标点击事件。
    4. 使用场景
    - 自定义控件行为:修改控件的默认行为,例如在按钮上添加额外的点击处理逻辑。
    - 事件监控:记录或调试事件,例如记录所有鼠标点击事件的位置和类型。
    - 跨控件事件处理:在一个地方集中处理多个控件的事件,例如处理所有按钮的点击事件。
4. 代码举例
//widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget> // 包含QWidget类的定义

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; } // 声明Qt UI命名空间
QT_END_NAMESPACE

// Widget类定义,继承自QWidget
class Widget : public QWidget
{
    Q_OBJECT // Qt的Meta-Object系统宏,用于支持信号和槽机制

public:
    // 构造函数,接受一个可选的父窗口指针
    Widget(QWidget *parent = nullptr);
    
    // 析构函数
    ~Widget();

    // 事件过滤器重写函数
    // 用于拦截并处理对象的事件
    bool eventFilter(QObject *watched, QEvent *event) override;

public slots:
//信号槽函数
    void btnClickedSlotFun();


private:
    // UI指针,指向自动生成的UI类
    Ui::Widget *ui;
};

#endif // WIDGET_H

//widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QMouseEvent>

Widget::Widget(QWidget *parent)
    : QWidget(parent)         // 调用基类QWidget的构造函数
    , ui(new Ui::Widget)      // 初始化UI指针
{
    ui->setupUi(this);        // 设置UI组件

    // 安装事件过滤器到不同的UI组件
    ui->label->installEventFilter(this);     // 监控ui->label的事件
    ui->btn->installEventFilter(this);       // 监控ui->btn的事件
    ui->labHover->installEventFilter(this);  // 监控ui->labHover的事件
    ui->labDBClick->installEventFilter(this); // 监控ui->labDBClick的事件
    connect(ui->btn,SIGNAL(clicked()),this,SLOT(btnClickedSlotFun()));
}

Widget::~Widget()
{
    delete ui;   // 释放UI指针的内存
}

bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    // 处理ui->label的事件
    if (watched == ui->label) {
        if (event->type() == QEvent::MouseButtonPress) {
            QMouseEvent *ev = static_cast<QMouseEvent *>(event); // 转换为QMouseEvent类型
            qDebug() << "label press" << ev->button() << "x=" << ev->x() << "y=" << ev->y(); // 输出鼠标点击信息
        } else if (event->type() == QEvent::Enter) {
            qDebug() << "label enter"; // 输出鼠标进入事件
        } else if (event->type() == QEvent::Leave) {
            qDebug() << "label leave"; // 输出鼠标离开事件
        }
    }

    // 处理ui->btn的事件
    else if (watched == ui->btn) {
        if (event->type() == QEvent::Enter) {
            static int a = 1; // 用于更新计数器
            ui->lineEdit->setText(QString("zhangsan = %1").arg(a++)); // 更新lineEdit的文本
            qDebug() << "btn enter"; // 输出鼠标进入事件
        } else if (event->type() == QEvent::Leave) {
            qDebug() << "btn leave"; // 输出鼠标离开事件
        }
    }

    // 处理ui->labHover的事件
    else if (watched == ui->labHover) {
        if (event->type() == QEvent::Enter) {
            ui->labHover->setStyleSheet("background-color: rgb(170, 255, 255);"); // 鼠标进入时改变背景颜色
        } else if (event->type() == QEvent::Leave) {
            ui->labHover->setStyleSheet(""); // 鼠标离开时恢复背景颜色
            ui->labHover->setText("靠近我,点击我"); // 恢复标签文本
        } else if (event->type() == QEvent::MouseButtonPress) {
            ui->labHover->setText("button pressed"); // 鼠标按下时更新标签文本
        } else if (event->type() == QEvent::MouseButtonRelease) {
            ui->labHover->setText("button released"); // 鼠标释放时更新标签文本
        }
    }

    // 处理ui->labDBClick的事件
    else if (watched == ui->labDBClick) {
        if (event->type() == QEvent::Enter) {
            ui->labDBClick->setStyleSheet("background-color: rgb(85, 255, 127);"); // 鼠标进入时改变背景颜色
        } else if (event->type() == QEvent::Leave) {
            ui->labDBClick->setStyleSheet(""); // 鼠标离开时恢复背景颜色
            ui->labDBClick->setText("可双击的标签"); // 恢复标签文本
        } else if (event->type() == QEvent::MouseButtonDblClick) {
            ui->labDBClick->setText("double clicked"); // 鼠标双击时更新标签文本
        }
    }

    // 调用基类的eventFilter方法,允许事件继续传播
    return QWidget::eventFilter(watched, event);
}

void Widget::btnClickedSlotFun()
{
    static int c = 1;
    qDebug()<<"c = "<<c;
}


在这里插入图片描述

5. QT事件类型

Qt事件类型

事件类事件类型事件描述
QMouseEventQEvent::MouseButtonDblClick鼠标双击
QEvent::MouseButtonPress鼠标按键按下,可以是左键或右键
QEvent::MouseButtonRelease鼠标按键释放,可以是左键或右键
QEvent::MouseMove鼠标移动
QWheelEventQEvent::Wheel鼠标滚轮滚动
QHoverEventQEvent::HoverEnter鼠标光标移动到组件上方并悬停(hover)
QEvent::HoverLeave鼠标光标离开某个组件上方
QEvent::HoverMove鼠标光标在组件上方移动
QEnterEventQEvent::Enter鼠标光标进入组件或窗口边界范围内
QEventQEvent::Leave鼠标光标离开组件或窗口边界范围
QKeyEventQEvent::KeyPress键盘按键按下
QEvent::KeyRelease键盘按键释放
QFocusEventQEvent::FocusIn组件或窗口获得键盘的输入焦点
QEvent::FocusOut组件或窗口失去键盘的输入焦点
QEvent::FocusAboutToChange组件或窗口的键盘输入焦点即将变化
QShowEventQEvent::Show窗口在屏幕上显示出来,或组件变得可见
QHideEventQEvent::Hide窗口在屏幕上隐藏(例如窗口最小化),或组件变得不可见
QMoveEventQEvent::Move组件或窗口的位置移动
QCloseEventQEvent::Close窗口被关闭,或组件被关闭,例如QTabWidget的一个页面被关闭
QPaintEventQEvent::Paint界面组件需要更新重绘
QResizeEventQEvent::Resize窗口或组件改变大小
QStatusTipEventQEvent::StatusTip请求显示组件的statusTip信息
QHelpEventQEvent::ToolTip请求显示组件的toolTip信息
QEvent::WhatsThis请求显示组件的whatsThis信息
QDragEnterEventQEvent::DragEnter在拖放操作中,鼠标光标移动到组件上方
QDragLeaveEventQEvent::DragLeave在拖放操作中,鼠标光标离开了组件
QDragMoveEventQEvent::DragMove拖放操作正在移动过程中
QDropEventQEvent::Drop拖放操作完成,即放下拖动的对象
QTouchEventQEvent::TouchBegin开始一个触屏事件序列(sequence)
QEvent::TouchCancel取消一个触屏事件序列
QEvent::TouchEnd结束一个触屏事件序列
QEvent::TouchUpdate触屏事件
QGestureEventQEvent::Gesture手势事件,能识别的手势有轻触、放大、扫屏等
QNativeGestureEventQEvent::NativeGesture操作系统检测到手势而产生的事件
QActionEventQEvent::ActionAdded运行QWidget::addAction()函数时会产生这种事件
QEvent::ActionChangedAction改变时触发的事件
QEvent::ActionRemoved移除Action时触发的事件

原文地址:https://blog.csdn.net/m0_51830537/article/details/140571368

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!