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);
}
相关推荐
「QT(C++)开发工程师」8 小时前
C++ auto 用法详解
开发语言·c++
OPEN-F8 小时前
C++STL教程:容器适配器与实用工具
开发语言·c++
OPEN-F9 小时前
C++模板教程:变参模板、折叠表达式与SFINAE
java·开发语言·c++
有点。9 小时前
C++二叉搜索树进阶
开发语言·c++
HugoStudio_SWAN9 小时前
【擦除重绘】C++ 控制台动画:弹跳 Logo DVD 屏保效果
开发语言·c++·学习·程序人生
kyle~10 小时前
C++_STL---迭代器失效
开发语言·c++
wuminyu12 小时前
深入剖析 Panama Off-heap 的性能损耗与开销
java·linux·c语言·jvm·c++
rhythm-ring12 小时前
宏定义续行符 \ 的使用与踩坑
c语言·c++
张人玉13 小时前
基于 Python 机器学习 与 PyQt5 桌面框架开发的可视化分析系统——基于大数据的网上购物消费行为分析可视化大屏
python·qt·机器学习·echarts·three.js
江安下小雨13 小时前
muduo网络库(十六):新增连接池模块
网络·c++