为什么设置 Qt::SplashScreen 标志阻止关闭

Why Setting Qt::SplashScreen flag prevent closing

我有 QMainWindow,其中嵌入了 QQuickWidget
QQuickWidget 根据应用程序的状态(是否初始化)显示两个不同的 qml(splash.qmlmain.qml)。

我希望我的 window 在显示 splash.qml 时处于 splashScreen 模式,所以我做到了:

MainWindow::MainWindow(QMainWindow * parent) :QMainWindow(parent)
{
    QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);

    mDefaultFlags = windowFlags();
    setAttribute(Qt::WA_DeleteOnClose, true);
    setWindowFlags(Qt::SplashScreen);

    mQuickWidget = new QQuickWidget(this);
    //...
    setCentralWidget(mQuickWidget);

    mQuickWidget->show();
}

当初始化完成并加载另一个 qml 文件时,QML 触发一个槽。然后我将标志重置为其默认值以从启动画面返回:

void MainWindow::UpdateWindowAfterInit()
{
    setWindowFlags(mDefaultFlags);
    show();
}

一切都按预期进行,但是当我尝试关闭我的应用程序时,它永远不会到达 main() 的末尾,而如果我不应用 Qt::SplashScreen 标志,它会很好地关闭。

我应该怎么做才能关闭我的应用程序?

首先,让我们试着理解为什么它没有像您预期的那样工作。

通过查看 QWidget::closedocumentation,我们有以下内容(强调我的):

The QApplication::lastWindowClosed() signal is emitted when the last visible primary window (i.e. window with no parent) with the Qt::WA_QuitOnClose attribute set is closed. By default this attribute is set for all widgets except transient windows such as splash screens, tool windows, and popup menus.

另一方面,Qt::WA_QuitOnClose:

Makes Qt quit the application when the last widget with the attribute set has accepted closeEvent(). This behavior can be modified with the QApplication::quitOnLastWindowClosed property. By default this attribute is set for all widgets of type Qt::Window.

因此怀疑您设置的属性或您认为设置的属性在您更改标志时实际上被重置了。

通过查看代码,我们有以下内容:

  • HeresetWindowFlags的实际实现。您可以看到,如果 旧类型是 window(也就是说,如果您设置了 Qt::Window 标志并且那是你的情况)。

  • HereadjustQuitOnCloseAttribute 的实际实现,这发生了:

    // ...
    
    if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
        q->setAttribute(Qt::WA_QuitOnClose, false);
    
    // ...
    

    这意味着当您设置标志 Qt::SplashScreen 时属性 Qt::WA_QuitOnClose 被设置为 false

最后,Qt::WA_DeleteOnClose

Makes Qt delete this widget when the widget has accepted the close event (see QWidget::closeEvent()).

因为你不再有 Qt::WA_QuitOnClose 集,window 不再接受 close 事件并且它不会被销毁。

更重要的是,它没有关闭,这就是您在应用程序中观察到的。这不是 Qt 的错误,它是一个(非常糟糕)记录的预期行为。


现在,我们可以想办法解决问题了。

可能以正确的顺序设置正确的标志和属性就足以解决它。
我不确定,但你可以试一试:

setWindowFlags(Qt::SplashScreen);
setAttribute(Qt::WA_QuitOnClose, true);
setAttribute(Qt::WA_DeleteOnClose, true);