34、事件的分发机制---------事件系统

事件的分发机制

Qt 的事件分发机制主要依赖于对象的继承关系和事件传递路径。Qt 提供了一套基于 QObject 的事件分发系统,使得事件能够在对象层次结构中传递。

1 事件分发的基本流程

1事件接收:当事件发生时,事件循环会创建一个 QEvent 对象,表示这个事件。

2事件队列:事件被放入目标对象的事件队列。

3事件处理:目标对象接收事件,并决定如何处理它(重绘、响应用户输入等)。

4事件传递:如果事件未被目标对象完全处理,事件可以传递到更高层的对象(如父对象)。

2 事件处理函数

每个 QObject 派生的类都可以通过重写特定的事件处理函数来响应事件。常见的事件处理函数包括:

●bool QWidget::event(QEvent *event):通用事件处理函数,处理所有类型的事件。可以根据事件类型进一步分发。

●void QWidget::mousePressEvent(QMouseEvent *event):处理鼠标按下事件。

●void QWidget::keyPressEvent(QKeyEvent *event):处理键盘按下事件。

●void QWidget::paintEvent(QPaintEvent *event):处理绘图事件。

这些事件处理函数可以被重写,以便在事件发生时执行特定的操作。

3 示例:重写事件处理函数

cpp 复制代码
#include <QApplication>
#include <QWidget>
#include <QMouseEvent>
#include <QMessageBox>

class MyWidget : public QWidget
{
protected:
    void mousePressEvent(QMouseEvent *event) override
    {
        QMessageBox::information(this, "Mouse Event",
                                 QString("Mouse pressed at (%1, %2)")
                                 .arg(event->x()).arg(event->y()));
    }

    void paintEvent(QPaintEvent *event) override
    {
        // 自定义绘图逻辑
        QPainter painter(this);
        painter.drawText(event->rect(), Qt::AlignCenter, "Hello, Qt!");
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    MyWidget widget;
    widget.resize(300, 200);
    widget.show();

    return app.exec();
}

重写event函数

我们不仅仅可以重写指定的事件,还可以重写event函数(通用事件处理函数),在event里根据事件类型做出判断,并且进行事件处理。

我们制作一个子部件ChildWidget,重新实现它的PaintEvent,绘制一个红色边框更显眼

然后重写event函数,判断鼠标点击事件弹出消息框

cpp 复制代码
class ChildWidget : public QLabel
{
public:
    ChildWidget(const QString &text, QWidget *parent = nullptr) : QLabel(text, parent)
    {
        setAlignment(Qt::AlignCenter);
    }

protected:

    void paintEvent(QPaintEvent * event) override{
        // 自定义绘图逻辑
        QPainter painter(this);
        // 设置背景颜色

        //设置画笔
        painter.setPen(QPen(Qt::red,2));

        // 绘制与控件相同大小的矩形
        painter.drawRect(rect());

        // 调用基类的 paintEvent
        QLabel::paintEvent(event);
    }

    bool event(QEvent *event) override
    {
        //如果是鼠标点击事件
        if (event->type() == QEvent::MouseButtonPress) {
            QMessageBox::information(this, "Child Event", "Child received mouse press event.");
            // 返回 false 以允许事件继续传递到父对象
            return false;
        }
        return QLabel::event(event);
    }
};

在main.cpp中创建这个ChildWidget,其父窗口为MainWindow,我们试试

cpp 复制代码
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.resize(800,600);
    //创建子部件,父窗口为MainWindow
    auto * child_wid = new ChildWidget("click me",&w);
    child_wid->setGeometry(100,100,100,50);
    //注意show为阻塞函数,所以创建工作要放在show上
    w.show();
    return a.exec();
}

运行后点击子部件,会看到弹出消息框

相关推荐
DY009J8 小时前
从 MSYS2 环境中提取独立 MinGW-w64 工具链的技术方案
c++·windows
xiaoye-duck8 小时前
《算法题讲解指南:动态规划算法--子数组系列》--25.单词拆分,26.环绕字符串中唯一的子字符串
c++·算法·动态规划
承渊政道8 小时前
【优选算法】(实战:栈、队列、优先级队列高频考题通关全解)
数据结构·c++·笔记·学习·算法·leetcode·宽度优先
liulilittle8 小时前
OPENPPP2 1.0.0.26145 正式版发布:内核态 SYSNAT 性能飞跃 + Windows 平台避坑指南
开发语言·网络·c++·windows·通信·vrrp
AIminminHu8 小时前
OpenGL渲染与几何内核那点事-项目实践理论补充(三-1-(2):当你的CAD代码变得“又大又乱”:从手动编译到CMake,从随性编码到单元测试))
c++·单元测试·cmake·cad·cad开发
xiaoye-duck9 小时前
《算法题讲解指南:动态规划算法--子数组系列》--23.等差数列划分,24.最长湍流子数组
c++·算法·动态规划
消失的旧时光-19439 小时前
C++ 网络服务端主线:从线程池到 Reactor 的完整路线图
开发语言·网络·c++·线程池·并发
cookies_s_s9 小时前
C++ 模板与泛型编程
linux·服务器·开发语言·c++
2401_892070989 小时前
【Linux C++ 日志系统实战】Logger 日志器完整实现:级别控制、宏封装、动态输出、自动崩溃退出
linux·c++·日志系统