I have QMainWindow
which embed a QQuickWidget
.
The QQuickWidget
display two differents qml (splash.qml
and main.qml
) according to the state of the app (initialized or not).
I want my window to be in splashScreen mode when the splash.qml
is displayed, so I did :
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();
}
The QML trigger a slot when the init is done and the other qml file is loaded. I then reset the flags to their default value to go back from splashscreen :
void MainWindow::UpdateWindowAfterInit()
{
setWindowFlags(mDefaultFlags);
show();
}
Everything goes as expected , but when I try to close my app it never reach the end of the main()
whereas it close nicely if i don't apply the Qt::SplashScreen
flag.
What should I do to be able to close my app ?
First of all, let's try to understand why it doesn't work as you expect.
By looking at the documentation of QWidget::close
, we have the following (emphasis mine):
The
QApplication::lastWindowClosed()
signal is emitted when the last visible primary window (i.e. window with no parent) with theQt::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.
On the other side, we have this for 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 theQApplication::quitOnLastWindowClosed
property. By default this attribute is set for all widgets of typeQt::Window
.
Therefore the suspect is that attributes you set or you think are set are actually reset when you change the flags.
By looking at the code, we have the following:
Here is the actual implementation of setWindowFlags
. You can see that the function adjustQuitOnCloseAttribute
is invoked if the old type was a window (that is, if you had the Qt::Window
flag set and that's your case).
Here is the actual implementation of adjustQuitOnCloseAttribute
and this happens:
// ...
if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
q->setAttribute(Qt::WA_QuitOnClose, false);
// ...
This means that attribute Qt::WA_QuitOnClose
is set to false
when you set the flag Qt::SplashScreen
.
Finally, we have the following for Qt::WA_DeleteOnClose
:
Makes Qt delete this widget when the widget has accepted the close event (see
QWidget::closeEvent()
).
For you don't have anymore the Qt::WA_QuitOnClose
set, the window no longer accepts the close
event and it is not destroyed.
More important, it is not closed, that is what you are observing in your application. This is not a bug of Qt, it is a (quite badly) documented intended behavior.
Now, we can try to figure what to do to solve the problem.
Probably, it's suffice to set the right flags and attributes in the right order to work around it.
I'm not sure about that, but you can give it a try:
setWindowFlags(Qt::SplashScreen);
setAttribute(Qt::WA_QuitOnClose, true);
setAttribute(Qt::WA_DeleteOnClose, true);