Problem with maximised window
-
At the end of the ctor for my main window, I have this code.
// // Set initial size of the bottom dock widget (pictureList) // resizeDocks({ pictureList }, { 150 }, Qt::Vertical); ZTRACE_RUNTIME("Restoring Window State and Position"); QSettings settings{}; settings.beginGroup("MainWindow"); if (settings.contains("geometry") && settings.contains("maximised")) { const QByteArray geometry{ settings.value("geometry").toByteArray() }; const bool maximised{ settings.value("maximised").toBool() }; if (maximised) { showMaximized(); setGeometry(screen()->availableGeometry()); } else { restoreGeometry(geometry); } } if (settings.contains("windowState")) { auto windowState{ settings.value("windowState").toByteArray() }; restoreState(windowState); } settings.endGroup();
and this is in closeEvent():
QSettings settings; settings.beginGroup("MainWindow"); auto geometry{ saveGeometry() }; settings.setValue("geometry", geometry); #ifndef NDEBUG ZTRACE_RUNTIME("Hex dump of geometry:"); ZTrace::dumpHex(geometry.constData(), geometry.length()); #endif auto windowState{ saveState()}; settings.setValue("windowState", windowState); #ifndef NDEBUG ZTRACE_RUNTIME("Hex dump of windowState:"); ZTrace::dumpHex(windowState.constData(), windowState.length()); #endif settings.setValue("maximised", isMaximized()); settings.endGroup();
If the application is maximised when closed, when it is re-opened, the title bar is off screen at the top and I need to move the window using keyboard actions to get it back on screen. When I do that the right end of the title bar indicates it is not maximised even though I invoked showMaximized(). Debugging through the code, I can see that the window IS shown maximised, and it's only when the restoreState call is made that the title bar is moved off screen.
Furthermore one of the (docked) dock windows is not always shown until I move and restore the application at which point it is shown with height 120.
So what is wrong with my save/restore code please?
-
At the end of the ctor for my main window, I have this code.
// // Set initial size of the bottom dock widget (pictureList) // resizeDocks({ pictureList }, { 150 }, Qt::Vertical); ZTRACE_RUNTIME("Restoring Window State and Position"); QSettings settings{}; settings.beginGroup("MainWindow"); if (settings.contains("geometry") && settings.contains("maximised")) { const QByteArray geometry{ settings.value("geometry").toByteArray() }; const bool maximised{ settings.value("maximised").toBool() }; if (maximised) { showMaximized(); setGeometry(screen()->availableGeometry()); } else { restoreGeometry(geometry); } } if (settings.contains("windowState")) { auto windowState{ settings.value("windowState").toByteArray() }; restoreState(windowState); } settings.endGroup();
and this is in closeEvent():
QSettings settings; settings.beginGroup("MainWindow"); auto geometry{ saveGeometry() }; settings.setValue("geometry", geometry); #ifndef NDEBUG ZTRACE_RUNTIME("Hex dump of geometry:"); ZTrace::dumpHex(geometry.constData(), geometry.length()); #endif auto windowState{ saveState()}; settings.setValue("windowState", windowState); #ifndef NDEBUG ZTRACE_RUNTIME("Hex dump of windowState:"); ZTrace::dumpHex(windowState.constData(), windowState.length()); #endif settings.setValue("maximised", isMaximized()); settings.endGroup();
If the application is maximised when closed, when it is re-opened, the title bar is off screen at the top and I need to move the window using keyboard actions to get it back on screen. When I do that the right end of the title bar indicates it is not maximised even though I invoked showMaximized(). Debugging through the code, I can see that the window IS shown maximised, and it's only when the restoreState call is made that the title bar is moved off screen.
Furthermore one of the (docked) dock windows is not always shown until I move and restore the application at which point it is shown with height 120.
So what is wrong with my save/restore code please?
The Qt 6.6 documentation on Restoring a Window's Geometry says that, "QWidget::saveGeometry() saves the window geometry and maximized/fullscreen state, while QWidget::restoreGeometry() restores it." (emphasis mine). This would mean that your attempt to save and restore the window state is unneeded and may be part of the problem.
Is this different for your Qt version? Does it work without capturing the window state?
The docs also explain some limitation on some platforms.
What platform and window manager is involved?
-
The Qt 6.6 documentation on Restoring a Window's Geometry says that, "QWidget::saveGeometry() saves the window geometry and maximized/fullscreen state, while QWidget::restoreGeometry() restores it." (emphasis mine). This would mean that your attempt to save and restore the window state is unneeded and may be part of the problem.
Is this different for your Qt version? Does it work without capturing the window state?
The docs also explain some limitation on some platforms.
What platform and window manager is involved?
@ChrisW67 Hmm... I'm not sure that is the case regarding windowState, especially given that the window state byte array is much larger than the geometry byte array. I need to restore the window state to restore the size of the docked dock widgets.
This problem is happening on Qt 6.5.1, Windows 11
@Axel-Spoerl Any thoughts?
-
@ChrisW67 Hmm... I'm not sure that is the case regarding windowState, especially given that the window state byte array is much larger than the geometry byte array. I need to restore the window state to restore the size of the docked dock widgets.
This problem is happening on Qt 6.5.1, Windows 11
@Axel-Spoerl Any thoughts?
Interesting: I reversed the order of the restoration so window state was restored first, but that made no difference.
Debugging through the geometry restoration, the call to showMaximized did show the window maximised but when I then let the application run the title bar was off screen again, and the maximised indicator in the window decorations showed it was not maximised.
-
I recall having seem similar problems and I think the issues I had were these two:
- trying to save the window geometry after it has been closed / or made invisible.
- trying to save a QByteArray as such with QVariant/QJson/QSetting silently failing.
For the second problem I now always base64 encode the byte arrays.
In general I find it's much better to make your applications shutdown sequence always explicit and in such a shutdown function you do stuff as saving your state while all your resources (such as windows) are still allocated.
Leave the destructor for simple cases only that have no impact on the program logic.
-
I recall having seem similar problems and I think the issues I had were these two:
- trying to save the window geometry after it has been closed / or made invisible.
- trying to save a QByteArray as such with QVariant/QJson/QSetting silently failing.
For the second problem I now always base64 encode the byte arrays.
In general I find it's much better to make your applications shutdown sequence always explicit and in such a shutdown function you do stuff as saving your state while all your resources (such as windows) are still allocated.
Leave the destructor for simple cases only that have no impact on the program logic.
-
@SamiV123 I'm saving the geometry etc. in closeEvent() not the dtor. So all windows should still be present and correct.
Changing the code to read:
if (settings.contains("geometry") && settings.contains("maximised")) { const QByteArray geometry{ settings.value("geometry").toByteArray() }; const bool maximised{ settings.value("maximised").toBool() }; if (maximised) { setGeometry(screen()->availableGeometry()); showMaximized(); } else { restoreGeometry(geometry); } }
That's to say calling showMaximized() AFTER setGeometry(screen()-> etc..) seems to have resolved the problem.
Can someone please clarify the officially correct way to do this and the exact order in which it should be done (window state, geometry, showMaximized()).
-
Changing the code to read:
if (settings.contains("geometry") && settings.contains("maximised")) { const QByteArray geometry{ settings.value("geometry").toByteArray() }; const bool maximised{ settings.value("maximised").toBool() }; if (maximised) { setGeometry(screen()->availableGeometry()); showMaximized(); } else { restoreGeometry(geometry); } }
That's to say calling showMaximized() AFTER setGeometry(screen()-> etc..) seems to have resolved the problem.
Can someone please clarify the officially correct way to do this and the exact order in which it should be done (window state, geometry, showMaximized()).
@Perdrix said in Problem with maximised window:
Changing the code to read:
if (settings.contains("geometry") && settings.contains("maximised")) { const QByteArray geometry{ settings.value("geometry").toByteArray() }; const bool maximised{ settings.value("maximised").toBool() }; if (maximised) { setGeometry(screen()->availableGeometry()); showMaximized(); } else { restoreGeometry(geometry); } }
That's to say calling showMaximized() AFTER setGeometry(screen()-> etc..) seems to have resolved the problem.
Can someone please clarify the officially correct way to do this and the exact order in which it should be done.
I think it's a red herring,
your "maximized" flag is saves as a bool in the settings so you get that value back properly while your geometry byte buffer is mangled.
Your maximized should be part of the geometry state already.
Try base64 encoding your geometry buffer like I suggested before.
-
@Perdrix said in Problem with maximised window:
Changing the code to read:
if (settings.contains("geometry") && settings.contains("maximised")) { const QByteArray geometry{ settings.value("geometry").toByteArray() }; const bool maximised{ settings.value("maximised").toBool() }; if (maximised) { setGeometry(screen()->availableGeometry()); showMaximized(); } else { restoreGeometry(geometry); } }
That's to say calling showMaximized() AFTER setGeometry(screen()-> etc..) seems to have resolved the problem.
Can someone please clarify the officially correct way to do this and the exact order in which it should be done.
I think it's a red herring,
your "maximized" flag is saves as a bool in the settings so you get that value back properly while your geometry byte buffer is mangled.
Your maximized should be part of the geometry state already.
Try base64 encoding your geometry buffer like I suggested before.
@SamiV123 I don't believe that's the case - please see:
https://bugreports.qt.io/browse/QTBUG-46620
and
David
-
@Perdrix said in Problem with maximised window:
Changing the code to read:
if (settings.contains("geometry") && settings.contains("maximised")) { const QByteArray geometry{ settings.value("geometry").toByteArray() }; const bool maximised{ settings.value("maximised").toBool() }; if (maximised) { setGeometry(screen()->availableGeometry()); showMaximized(); } else { restoreGeometry(geometry); } }
That's to say calling showMaximized() AFTER setGeometry(screen()-> etc..) seems to have resolved the problem.
Can someone please clarify the officially correct way to do this and the exact order in which it should be done.
I think it's a red herring,
your "maximized" flag is saves as a bool in the settings so you get that value back properly while your geometry byte buffer is mangled.
Your maximized should be part of the geometry state already.
Try base64 encoding your geometry buffer like I suggested before.
Arghh! If I now close the application while it is maximised and restart it, when I restore the window from maximised it doesn't go back the the size it was before it was maximised, but to the default initial size that would apply if there were no saved geometry or state.
If I maximise/restore without closing everything works as I expect.
David
-
I just checked what I've done in my own app, I also have a "MainWindow" with a QDockWidget and all I seem to be doing is to call QMainWindow::saveState and then restoreState and this works for me for restoring the dock state.
Then I use x(), y(), width() and height() to save the window geometry explicitly.
This has worked for me on Linux with X11 including fully maximized window.
FWIW I'm also doing the base64 encode step since I also spent time struggling with this same problem.
-
I just checked what I've done in my own app, I also have a "MainWindow" with a QDockWidget and all I seem to be doing is to call QMainWindow::saveState and then restoreState and this works for me for restoring the dock state.
Then I use x(), y(), width() and height() to save the window geometry explicitly.
This has worked for me on Linux with X11 including fully maximized window.
FWIW I'm also doing the base64 encode step since I also spent time struggling with this same problem.
@Volker-Hilsheimer Any thoughts?
-
@Volker-Hilsheimer Any thoughts?
Reported under https://bugreports.qt.io/browse/QTBUG-118598