35、事件传递模式---------事件系统

事件传递模式

Qt 的事件传递遵循一定的模式,特别是在使用继承和父子对象体系时。主要有两种事件传递方式:

1直接事件传递:事件直接发送到目标对象。

2事件链传递(Event Chain):事件从目标对象传递到其父对象,直到被处理或达到顶层对象。

1 直接事件传递

直接事件传递是指事件被发送到指定的目标对象,并由该对象直接处理。例如,点击按钮时,事件直接发送到按钮对象。

发送事件的方式:

●同步发送:使用 QCoreApplication::sendEvent(QObject *receiver, QEvent *event)。事件被立即发送并处理,调用方等待处理完成。

●异步发送:使用 QCoreApplication::postEvent(QObject *receiver, QEvent *event)。事件被放入接收者的事件队列,等待事件循环处理。

这个稍后我们自定义事件的时候可以用一下,目前做个了解。

2 事件链传递

事件链传递是指事件在目标对象、其父对象及进一步的父对象中逐级传递,直到被处理或到达事件链的顶端。

事件链的传递顺序如下:

1事件过滤器:在事件传递到目标对象之前,事件可以被安装在目标对象或其父对象上的事件过滤器拦截和处理,事件过滤器之后讲解

2目标对象:首先尝试由目标对象处理事件。

3父对象:如果目标对象未处理事件,事件将被传递到其父对象,依此类推,直到顶层对象(通常是 QApplication)。

4默认处理:如果事件链上的所有对象都未处理事件,则事件最终会被系统的默认事件处理程序处理。

注意

要想让事件传递链生效,需要在目标对象的event处理函数里返回false,表示未处理完全,这样其父节点依次处理。

3 示例:事件链传递

我们定义一个ChildWidget继承自QLabel,重写paintEvent绘制区域,和event事件处理点击事件。

再定义一个ParentWiget,继承自QWidget,重写event事件处理点击事件

然后让ChildWidget成为ParentWidget的子部件

cpp 复制代码
class ParentWidget : public QWidget
{
    Q_OBJECT
public:
    explicit ParentWidget(QWidget *parent = nullptr);
    bool event(QEvent *event) override
    {
        if (event->type() == QEvent::MouseButtonPress) {
            QMessageBox::information(this, "Parent Event", "Parent received mouse press event.");
            //返回true不向上传递
            return true;
        }
        //其他事件类型调用基类默认处理
        return QWidget::event(event);
    }
signals:

public slots:
};


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);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ParentWidget parent;
    parent.resize(300, 200);

    ChildWidget *child = new ChildWidget("Click Me", &parent);
    child->setGeometry(50, 50, 200, 100);

    parent.show();
    return a.exec();
}

在这个示例中,当用户点击标签(ChildWidget)时:

  1. 事件首先被发送到 ChildWidget
  2. ChildWidgetevent 方法处理事件,并弹出一个消息框。
  3. 返回 false,表示事件未被完全处理,事件继续传递到其父对象 ParentWidget
  4. ParentWidgetevent 方法接收同一个事件,并弹出另一个消息框。

如果将 ChildWidget::event 返回 true,事件将不会传递到 ParentWidget

cpp 复制代码
bool event(QEvent *event) override
{
    if (event->type() == QEvent::MouseButtonPress) {
        QMessageBox::information(this, "Child Event", "Child received mouse press event.");
        // 返回 true 不允许事件继续传递到父对象
        return true;
    }
    return QLabel::event(event);
}
相关推荐
啦啦啦啦啦zzzz4 小时前
算法:回溯算法
c++·算法·leetcode
Lzg_na4 小时前
订阅发布模块事例
c++
汉克老师5 小时前
2026年CSP-J初赛分数线-----预测
c++·csp-j·小学生·学c++编程
脱胎换骨-军哥5 小时前
C++数据库存储引擎内核开发:B+树索引与MVCC并发控制的完整实现
数据库·c++·b树
小保CPP5 小时前
OpenCV C++将多张图像合并为webp动图
c++·人工智能·opencv·计算机视觉
乐观勇敢坚强的老彭6 小时前
信奥C++一维数组笔记
开发语言·c++·笔记
码上有光6 小时前
异常和智能指针
java·大数据·c++·servlet·异常·智能指针
王维同学6 小时前
[原创][Windows C++]Explorer Shell 扩展、图标覆盖与 COM 服务器定位
c++·windows·注册表
code_pgf6 小时前
C++ 工程架构设计规范
c++·机器人
C++ 老炮儿的技术栈6 小时前
基于MFC+原生GDI手动自绘仪表盘控件
c语言·c++·visual studio·控件·工业控制·gdi·自绘