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);
}
相关推荐
故事和你911 小时前
蓝桥杯-2025年C++B组国赛
开发语言·软件测试·数据结构·c++·算法·职场和发展·蓝桥杯
cpp_25012 小时前
P10108 [GESP202312 六级] 闯关游戏
数据结构·c++·算法·动态规划·题解·洛谷·gesp六级
kvo7f2JTy2 小时前
吃透Linux/C++系统编程:文件与I/O操作从入门到避坑
java·linux·c++
崽崽..2 小时前
【面经】shared_ptr的线程安全问题
c++
AbandonForce2 小时前
模拟实现vector
开发语言·c++·算法
海参崴-2 小时前
C++代码格式规范
java·前端·c++
怎么没有名字注册了啊2 小时前
崩溃解决_Qt子窗口关闭按钮后打开崩溃
开发语言·qt
!停3 小时前
C++入门—初阶模板
开发语言·c++
Jp7gnUWcI3 小时前
C++ 内存避坑指南:如何用移动语义和智能指针解决“深拷贝”与“内存泄漏”
开发语言·c++