QCloseEvent 如何传播?

How does a QCloseEvent propagate?

我有一个从 QMainWindow 派生的 MainWindow,我重新实现了 closeEvent() 处理程序。

void MainWindow::closeEvent(QCloseEvent *event)
{
    if (this->okToContinue()) {
        this->writeSettings();
        //event->accept();
        QMainWindow::closeEvent(event); // will work just fine even if this line omitted
    } else {
        event->ignore();
    }
}

我已经注释掉了 QMainWindow::closeEvent() 以测试应用程序将在没有事件传播到基本实现的情况下退出。奇怪的是,它确实退出了。

我可以将 event->ignore() 放在 if-else 语句之外以防止退出,但这不是重点。

其他事件处理程序如 keyPressEvent() 在其覆盖中没有基本实现时无法正常工作,但 closeEvent() 在没有基本实现的情况下也能正常工作。(除非,当然,你重新实现一切)

void LineEdit::keyPressEvent(QCloseEvent *event)
{
    QLineEdit::keyPressEvent(event); // will not show text in the widget if omitted
}

根据我在文档中收集到的信息,一旦一个事件被小部件处理,它就不会进一步传播,除非明确允许。 (即在子 keyPressEvent() 的实现中调用基础的 keyPressEvent())

但是,子级的 closeEvent() 将关闭应用程序,而无需在其实现中调用基础的 closeEvent()。似乎它传播到其他地方。

是什么原因造成的?即使 QCloseEvent 已被处理,它是否会传播到其他小部件?

多么好的问题。 (我从来没有想过这个。)

这引起了我的好奇心之后,我调查了一下。这就是 OpenSource 软件的优点——如果您有疑问,只需查看源代码即可。所以,我在 woboq.org:

上挖掘了一下

首先,我在 qmainwindow.cpp 中寻找 closeEvent(),但到处都找不到。

qmainwindow.h.

也一样

所以,我假设 QMainWindow 不会覆盖 closeEvent()

QMainWindow 派生自 QWidget 很容易在文档中找到。或者直接在我手边的源代码中:

class Q_WIDGETS_EXPORT QMainWindow : public QWidget

因此,我切换到 qwidget.h 声明

 virtual void closeEvent(QCloseEvent *event);

(目前在 line 634)。

再次点击,我接近了 qwidget.cpp:9936:

void QWidget::closeEvent(QCloseEvent *event)
{
    event->accept();
}

啊,是的。

这很好地解释了为什么调用base class方法

    QMainWindow::closeEvent(event);

与对

的简单调用一样有效
    event->accept();

或者两者兼而有之。

不过,我更喜欢调用基础 class 事件处理程序。

我认为这是一般有用的经验法则(或成语?):

  • 如果基础 class 的行为应 扩展 则在您的覆盖中调用基础 class 事件处理程序。

  • 如果基 class 的行为应 替换 则不要调用基 class 事件处理程序。

当然,这是一般的经验法则,应根据必须处理的具体事件重新检查。

(如有疑问,还有woboq.org...)