I have essentially two buttons in a grid layout, with code written to save window size when refreshing the program. However, this presents one issue--despite having the window size saved, the window will always expand slightly, which becomes more and more noticeable as you reload the program again and again.
Here's my code if you want to see the effect:
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from configparser import ConfigParser
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.loadDefaults()
self.resize(int(self.windowWidth),int(self.windowHeight))
self.setSizePolicy(QSizePolicy.Policy.Fixed,QSizePolicy.Policy.Fixed)
size=QSize(int(self.windowWidth),int(self.windowHeight))
container=QWidget()
layout=QGridLayout()
button=QPushButton("button1")
button2=QPushButton("button2")
layout.addWidget(button)
layout.addWidget(button2)
container.setLayout(layout)
self.setCentralWidget(container)
def resizeEvent(self, a0: QResizeEvent) -> None:
self.windowWidth=self.frameGeometry().width()
self.windowHeight=self.frameGeometry().height()
self.saveSettings()
return super().resizeEvent(a0)
def loadDefaults(self):
config=ConfigParser()
config.read('config.ini')
try:
config.add_section('settings')
config['settings']={
'windowWidth':int(self.screen().size().width()/2),
'windowHeight':int(self.screen().size().height()/2),
}
self.windowWidth=self.screen().size().width()/2
self.windowHeight=self.screen().size().height()/2
print("no ini file")
except:
self.windowWidth=config['settings'].getint('windowWidth')
self.windowHeight=config['settings'].getint('windowHeight')
print("ini file found")
with open('config.ini', 'w') as f:
config.write(f)
def saveSettings(self):
config=ConfigParser()
config.read('config.ini')
config['settings']={
'windowWidth':self.windowWidth,
'windowHeight':self.windowHeight,
}
with open('config.ini', 'w') as f:
config.write(f)
app=QApplication(sys.argv)
window=MainWindow()
window.show()
sys.exit(app.exec())
How can I prevent the window from resizing due to its child widgets, without forcing either of those aspects to have a fixed size?
I've looked into several posts:
The problem is that you are using the frameGeometry()
to get the current size, but that is inconsistent with resize()
(or its main counterpart, setGeometry()
), as shown in the documentation:
Using frameGeometry()
you will get the outer boundaries of the window frame, but the documentation about the size
property (including the setter function resize()
) is clear:
This property holds the size of the widget excluding any window frame
The result is that you're always storing a larger window size, and, since resize()
doesn't consider the window frame, when you reload the configuration the window will be bigger, and the increment will exactly be the size of the frame width.
So, the simplest solution would be to use size()
instead of frameGeometry()
.
Be aware, though, that Qt already provides this functionality, and that's through the saveGeometry()
and restoreGeometry()
functions.
Now the problem is that the returned data is a QByteArray (fundamentally, a byte array), and ConfigParser only supports ordinary strings. While you could try to convert that data to strings (for instance, using hex or base64), Qt can still help us: use the QSettings API instead, which supports a more flexible way of storing data.
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
container = QWidget()
layout = QGridLayout(container)
button = QPushButton("button1")
button2 = QPushButton("button2")
layout.addWidget(button)
layout.addWidget(button2)
self.setCentralWidget(container)
self.settings = QSettings()
if self.settings.contains('geometry'):
try:
self.restoreGeometry(self.settings.value('geometry'))
except TypeError:
pass
def resizeEvent(self, a0: QResizeEvent) -> None:
self.settings.setValue('geometry', self.saveGeometry())
return super().resizeEvent(a0)
app = QApplication(sys.argv)
app.setOrganizationName('My Company')
app.setApplicationName('My App')
window = MainWindow()
window.show()
sys.exit(app.exec())
Note that the size policy is only considered for widgets added to layout managers; setting it for a top level window is completely useless.
If you want to prevent the user to resize the window, do any of the following:
self.setMaximumSize(self.sizeHint())
after adding all widgets to the window (usually, near the end of the __init__
);MSWindowsFixedSizeDialogHint
window flag: self.setWindowFlag(Qt.MSWindowsFixedSizeDialogHint)
;window.layout().setSizeConstraint(QLayout.SetFixedSize)
; note that if you're using a QMainWindow, you have to call that on the layout of the main window itself, not on that of the central widget;