我有一个从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();
}

嗯是的

这很好地解释了为什么调用基类方法
    QMainWindow::closeEvent(event);

就像一个简单的调用一样
    event->accept();

甚至两者兼而有之。

虽然,我更喜欢基类事件处理程序的调用。

我认为这是一般有用的经验法则(或成语?):
  • 如果应扩展基类的行为,则在您的重写中调用基类事件处理程序。
  • 如果应替换基类的行为,则不要调用基类事件处理程序。

  • 当然,这是一般的经验法则,应根据必须处理的特定事件进行重新检查。

    (如果有疑问,仍然还有woboq.org ...)

    10-06 06:22