当前位置: 首页 > article >正文

【QA】QT事件处理流程是怎么样的?

Qt 事件流程详解

1. 事件流程概述

在 Qt 中,事件处理是实现用户交互和系统响应的核心机制。整个事件流程从事件产生开始,经过事件队列的管理、事件分发,最终到达目标对象进行处理,若未处理还会进行事件传播。

2. 详细流程步骤及代码示例
2.1 事件产生

事件可以由多种方式产生,包括用户输入、系统消息和程序主动发送自定义事件。

用户输入事件示例

#include <QApplication>
#include <QWidget>
#include <QPushButton>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QWidget window;
    QPushButton button("Click me", &window);
    button.show();
    window.show();
    return app.exec();
}

当用户点击按钮时,会产生鼠标点击事件。

系统消息事件示例:当窗口大小改变时,会产生 QResizeEvent。以下是一个简单的窗口大小改变事件处理示例:

#include <QApplication>
#include <QWidget>
#include <QDebug>

class MyWidget : public QWidget {
protected:
    void resizeEvent(QResizeEvent *event) override {
        qDebug() << "Window resized to" << event->size();
        QWidget::resizeEvent(event);
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyWidget widget;
    widget.show();
    return app.exec();
}
2.2 事件队列

事件产生后会被添加到 QApplication 的事件队列中,QApplication 会不断从队列中取出事件进行分发。

2.3 事件分发

QApplication 通过 notify 函数将事件从队列中取出并分发给目标对象。以下是一个简单的自定义 QApplication 子类,重写 notify 函数来展示事件分发过程:

#include <QApplication>
#include <QWidget>
#include <QDebug>

class MyApplication : public QApplication {
public:
    MyApplication(int &argc, char **argv) : QApplication(argc, argv) {}

    bool notify(QObject *receiver, QEvent *event) override {
        qDebug() << "Dispatching event" << event->type() << "to" << receiver->objectName();
        return QApplication::notify(receiver, event);
    }
};

int main(int argc, char *argv[]) {
    MyApplication app(argc, argv);
    QWidget window;
    window.setObjectName("MainWindow");
    window.show();
    return app.exec();
}
2.4 事件处理

目标对象接收到事件后,首先检查是否安装了事件过滤器,如果有则先调用事件过滤器进行处理;如果事件过滤器未处理该事件,则调用目标对象的 event 函数进行处理;event 函数会根据事件类型调用相应的特定事件处理函数。

事件过滤器示例

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QDebug>

class MyEventFilter : public QObject {
protected:
    bool eventFilter(QObject *watched, QEvent *event) override {
        if (event->type() == QEvent::MouseButtonPress) {
            qDebug() << "Event filter intercepted mouse press event on" << watched->objectName();
            return true; // 事件已处理,不再传递
        }
        return QObject::eventFilter(watched, event);
    }
};

class MyWidget : public QWidget {
public:
    MyWidget(QWidget *parent = nullptr) : QWidget(parent) {
        QPushButton *button = new QPushButton("Click me", this);
        button->setObjectName("MyButton");
        MyEventFilter *filter = new MyEventFilter(this);
        button->installEventFilter(filter);
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyWidget widget;
    widget.show();
    return app.exec();
}

目标对象 event 函数处理示例

#include <QApplication>
#include <QWidget>
#include <QDebug>

class MyWidget : public QWidget {
protected:
    bool event(QEvent *event) override {
        if (event->type() == QEvent::MouseButtonPress) {
            qDebug() << "Mouse press event handled in event function";
            return true;
        }
        return QWidget::event(event);
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyWidget widget;
    widget.show();
    return app.exec();
}

特定事件处理函数示例

#include <QApplication>
#include <QWidget>
#include <QDebug>

class MyWidget : public QWidget {
protected:
    void mousePressEvent(QMouseEvent *event) override {
        qDebug() << "Mouse press event handled in mousePressEvent function";
        QWidget::mousePressEvent(event);
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyWidget widget;
    widget.show();
    return app.exec();
}
2.5 事件传播

如果目标对象没有处理该事件(即特定事件处理函数或 event 函数返回 false),事件会传播给其父对象,直到事件被处理或到达顶层对象。

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QDebug>

class ChildWidget : public QWidget {
protected:
    void mousePressEvent(QMouseEvent *event) override {
        qDebug() << "ChildWidget: Mouse press event not handled, propagating";
        // 不调用父类的 mousePressEvent,让事件传播
    }
};

class ParentWidget : public QWidget {
protected:
    void mousePressEvent(QMouseEvent *event) override {
        qDebug() << "ParentWidget: Handling propagated mouse press event";
        QWidget::mousePressEvent(event);
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    ParentWidget parent;
    ChildWidget child(&parent);
    child.show();
    parent.show();
    return app.exec();
}

3. Mermaid 代码图

处理成功
未处理
处理成功
未处理
父对象处理成功
父对象未处理
事件产生
用户输入/系统消息/自定义
事件队列
事件分发
QApplication::notify
是否有事件过滤器?
事件过滤器处理
事件结束
目标对象 event 函数
是否有特定事件处理函数?
特定事件处理函数
事件传播给父对象
继续传播

4. 自定义事件流程

4.1 自定义事件步骤
  • 定义自定义事件类型:通过继承 QEvent 类定义自定义事件,并为其分配一个唯一的事件类型。
  • 创建自定义事件对象:在需要发送自定义事件的地方,创建自定义事件对象。
  • 发送自定义事件:使用 QCoreApplication::postEventQCoreApplication::sendEvent 发送自定义事件。
  • 处理自定义事件:在目标对象的 event 函数中处理自定义事件。
4.2 自定义事件代码示例
#include <QApplication>
#include <QWidget>
#include <QDebug>

// 定义自定义事件类型
const QEvent::Type MyCustomEventType = static_cast<QEvent::Type>(QEvent::User + 1);

// 自定义事件类
class MyCustomEvent : public QEvent {
public:
    MyCustomEvent(int data) : QEvent(MyCustomEventType), m_data(data) {}
    int getData() const { return m_data; }
private:
    int m_data;
};

// 自定义窗口类
class MyWidget : public QWidget {
protected:
    bool event(QEvent *event) override {
        if (event->type() == MyCustomEventType) {
            MyCustomEvent *customEvent = static_cast<MyCustomEvent*>(event);
            qDebug() << "Custom event handled in MyWidget with data:" << customEvent->getData();
            return true;
        }
        return QWidget::event(event);
    }
};

// 自定义定时器类,用于定时发送自定义事件
class MyTimer : public QObject {
    Q_OBJECT
public:
    MyTimer(QObject *parent = nullptr) : QObject(parent) {
        m_timer = new QTimer(this);
        connect(m_timer, &QTimer::timeout, this, &MyTimer::sendCustomEvent);
        m_timer->start(1000); // 每秒发送一次自定义事件
    }

    void setTargetWidget(MyWidget *widget) {
        m_targetWidget = widget;
    }

private slots:
    void sendCustomEvent() {
        if (m_targetWidget) {
            MyCustomEvent *customEvent = new MyCustomEvent(42);
            QCoreApplication::postEvent(m_targetWidget, customEvent);
        }
    }

private:
    QTimer *m_timer;
    MyWidget *m_targetWidget = nullptr;
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyWidget widget;
    widget.show();

    MyTimer timer;
    timer.setTargetWidget(&widget);

    return app.exec();
}

#include "main.moc"

5. 自定义事件 Mermaid 代码图

定义自定义事件类型
创建自定义事件对象
发送自定义事件
QCoreApplication::postEvent
事件队列
事件分发
QApplication::notify
目标对象 event 函数
是否为自定义事件?
处理自定义事件
事件结束
按常规事件处理

通过以上详细的代码示例和 Mermaid 图,你可以全面了解 Qt 中的事件流程以及自定义事件的处理流程。


http://www.kler.cn/a/599034.html

相关文章:

  • Linux内核Netfilter框架分析
  • 【CC2530 教程 二】CC2530定时器实现微秒、毫秒、秒延时函数
  • 【Vue3入门1】04-计算属性 + 侦听器
  • 01 Java微服务架构(SpringBootSpringCloudJDK)_企业级升级方案指导手册
  • 【计算机操作系统】深入剖析操作系统中的存储器管理:从基础到高级
  • LORA 中的 梯度外积是什么意思; 方差和协方差的实际含义:衡量变量的离散程度和变量间的线性相关性
  • 在linux上启动微服务
  • MySQL 的多版本并发控制
  • 【IntelliJ IDEA快速绑定Maven配置指南】
  • 奇安信2面面试题。。。
  • 基于Python的智慧金融风控系统的设计与实现
  • Spring MVC 执行流程:一个请求在 Spring MVC 中是如何执行的?
  • qt实现一个简单http服务器和客户端
  • 豪越科技消防一体化:数字中国智慧应急的关键支撑
  • Vue3自定义指令实现前端权限控制 - 按钮权限
  • 全球新闻系统发布 -- 项目启动环节
  • 固定翼无人机姿态和自稳模式
  • 区块链技术
  • [笔记] TinyWebServer编译及demo运行过程
  • React-Router路由跳转、传参、抽象封装以及嵌套路由