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);
}
相关推荐
小小编程路8 小时前
C++ 多线程与并发
java·jvm·c++
程序leo源9 小时前
Qt窗口详解
开发语言·数据库·c++·qt·青少年编程·c#
zh_xuan10 小时前
解决VS Code 控制台中文乱码
c++·vscode·乱码
郭涤生10 小时前
飞凌 RK3588 开发板同显 / 异显模式切换
c++·rk3588
计算机安禾10 小时前
【c++面向对象编程】第38篇:设计原则(二):里氏替换、接口隔离与依赖倒置
开发语言·c++
我在人间贩卖青春10 小时前
重学Qt——事件处理
qt
code_whiter10 小时前
C++1进阶(继承)
开发语言·c++
小宋00110 小时前
QT中控件qss样式修改
开发语言·qt
智者知已应修善业11 小时前
【51单片机LED闪烁10次数码管显示0-9】2023-12-14
c++·经验分享·笔记·算法·51单片机
智者知已应修善业11 小时前
【51单片机2按键控制1个敞亮LED灯闪烁和熄灭】2023-11-3
c++·经验分享·笔记·算法·51单片机