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

时间:2016-11-03 15:56:13

标签: c++ qt qml qwindow

QMainWindow嵌入QQuickWidget QQuickWidget根据应用的状态显示两个不同的qml(splash.qmlmain.qml)(已初始化或未初始化)。

我希望在显示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();
}

当init完成并加载另一个qml文件时,QML会触发一个插槽。然后我将标志重置为默认值以从splashscreen返回:

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

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

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

1 个答案:

答案 0 :(得分:1)

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

通过查看QWidget::close的{​​{3}},我们有以下内容(强调我的):

  

当最后一个可见主窗口(即没有父窗口)并设置了QApplication::lastWindowClosed() 属性时,会发出Qt::WA_QuitOnClose信号。 默认情况下,为除瞬态窗口(如启动画面),工具窗口和弹出菜单之外的所有窗口小部件设置此属性。

另一方面,我们为Qt::WA_QuitOnClose

提供此功能
  

当具有属性集的最后一个窗口小部件已接受closeEvent()时,Qt退出应用程序。可以使用QApplication::quitOnLastWindowClosed属性修改此行为。默认情况下,为Qt::Window类型的所有窗口小部件设置此属性。

因此,嫌疑人是您更改标志时实际上重置了您设置或您认为已设置的属性。

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

  • documentationsetWindowFlags的实际实现。如果旧类型是一个窗口(也就是说,如果你设置了adjustQuitOnCloseAttribute标志并且那是你的情况,你可以看到函数Qt::Window被调用)。

  • HereadjustQuitOnCloseAttribute的实际实现,并且会发生这种情况:

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

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

最后,Qt::WA_DeleteOnClose我们有以下内容:

  

当窗口小部件接受关闭事件时,Qt删除此窗口小部件(请参阅QWidget::closeEvent())。

对于您不再拥有Qt::WA_QuitOnClose集,该窗口不再接受close事件且不会被销毁。

更重要的是,它并未关闭,这是您在应用程序中观察到的内容。这不是Qt的错误,它是(非常严重的)记录的预期行为。

现在,我们可以尝试找出解决问题的方法。

可能只需按正确的顺序设置正确的标志和属性即可解决问题。
我不确定,但你可以尝试一下:

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