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
不会覆盖 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...)
我有一个从 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
不会覆盖 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...)