I'm using PyQt5 to create an app with multiple main windows. I want to be able to allow the user to save and load window sizes and window positions. That's easy with, e.g., QMainWindow.saveGeometry()
and QMainWindow.loadGeometry()
or the corresponding .saveState()
and .loadState()
variants. These work great for position and size, but if the user moves or resizes one window so that it occludes another, I want to also restore this positioning. I don't mind writing my own code to save the info for each window, but I can't see any way to detect the relative Z order of windows. Am I missing it in the docs, or is this not possible?
To see what I mean, try this:
from PyQt5.QtWidgets import QApplication, QMainWindow, QPlainTextEdit
from PyQt5.QtCore import QSettings
from PyQt5.QtGui import QCloseEvent
'''
context: Linux Mint 19.3 Tricia x86_64
Python 3.9
PyQt5 5.15.1
'''
class RememberWin(QMainWindow):
def __init__(self, win_name: str):
super(RememberWin, self).__init__()
self.win_name = win_name
self.setWindowTitle(win_name)
self.can_close = False
def restore_window(self) -> bool:
try:
settings = QSettings("PyQtExamples", "RememberWinTest")
self.restoreGeometry(settings.value(f'{self.win_name} Geometry'))
self.restoreState(settings.value(f'{self.win_name} State'))
return True
except:
return False
def closeEvent(self, event: QCloseEvent):
if not self.can_close:
event.ignore()
else:
settings = QSettings("PyQtExamples", "RememberWinTest")
settings.setValue(f'{self.win_name} Geometry', self.saveGeometry())
settings.setValue(f'{self.win_name} State', self.saveState())
QMainWindow.closeEvent(self, event)
class ControlWindow(RememberWin):
def __init__(self, win_name: str = "ControlWindow"):
super(ControlWindow, self).__init__(win_name=win_name)
self.can_close = True
self.window1 = RememberWin(win_name='WindowOne')
self.window2 = RememberWin(win_name='WindowTwo')
self.text = QPlainTextEdit(self)
s = "Try making Window1 wide enough to cover Window2.\n" \
"Then close this window (auto closes others).\n" \
"Re-run the app and you'll notice that Window2\n" \
"is not on top of Window1 which means that this\n" \
"info isn't getting saved."
self.text.setPlainText(s)
self.setCentralWidget(self.text)
if not self.restore_window():
self.setGeometry(100, 390, 512, 100)
if not self.window1.restore_window():
self.window1.setGeometry(100, 100, 512, 384)
if not self.window2.restore_window():
self.window2.setGeometry(622, 100, 512, 384)
self.window1.show()
self.window2.show()
def closeEvent(self, event: QCloseEvent):
for win in (self.window1, self.window2):
win.can_close = True
win.close()
super(ControlWindow, self).closeEvent(event)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = ControlWindow(win_name='ControlWindow (You can only close this one)')
window.show()
sys.exit(app.exec_())