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

【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 中的事件流程以及自定义事件的处理流程。

相关文章:

  • 如何理解前端工程化
  • 蓝桥杯备考:差分算法之 语文成绩
  • 信号的产生和保存
  • Netty源码—5.Pipeline和Handler一
  • Vue3+vite项目 使用require 解决 ReferenceError: require is not defined 报错问题
  • CodeBrick笔记
  • Jenkins集成Trivy安全漏洞检查指南
  • venv 和 conda 哪个更适合管理python虚拟环境
  • 【C#】将数字转换为中文,如123转换为一百二十三
  • 卷积神经网络 - 参数学习
  • NVIDIA V100显卡支持Tensor Core技术,而Granite-3.1-8B模型在适当的条件下可以利用Tensor Core来加速数据处理
  • 二分图相关
  • 03 Python 基础:数据类型、运算符与流程控制解析
  • AIP-180 向后兼容
  • 统计矩的高阶推广:经验还是理论推导?
  • 计算图(Computation Graph)
  • git revert 用法实战:撤销一个 commit 或 merge
  • Go常见问题与回答(下)
  • 数据可视化革命!「图表狐」五大行业新范式:从科研论文到商业决策的AI进化论
  • 软件公司高新技术企业代办:机遇与陷阱并存-优雅草卓伊凡
  • 国家卫健委有关负责人就白皮书发布答记者问
  • 中信银行一季度净利195.09亿增1.66%,不良率持平
  • 夜读丨跷脚牛肉乐翘脚
  • 五大国有银行明确将撤销监事会
  • 阿里开源首个“混合推理模型”:集成“快思考”、“慢思考”能力
  • 西班牙葡萄牙突发全国大停电,欧洲近年来最严重停电事故何以酿成