PyQt5如何阻止子部件导致窗口自动调整大小?
PyQt5窗口重启后持续放大+阻止布局拉伸窗口的解决方案
问题描述
我在网格布局中放置两个按钮,实现了重启程序时保存窗口大小的功能,但每次重启窗口都会轻微放大,多次重启后问题更明显。同时希望不设置固定尺寸的前提下,阻止窗口因布局内的子部件自动调整大小。
复现代码:
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())
问题分析
- 尺寸保存错误:
frameGeometry()获取的是包含窗口边框、标题栏的整体尺寸,但resize()设置的是窗口客户区(不含边框)的尺寸,每次保存的尺寸比实际需要的客户区大,重启后叠加边框导致窗口越来越大。 - 布局自动拉伸:默认布局会根据子部件的最小尺寸调整窗口,需要限制布局的尺寸约束。
解决方案
关键修改点
- 替换尺寸获取方式:用
self.size()获取客户区尺寸,保存和加载都使用这个值,避免边框带来的误差。 - 重写
sizeHint():返回固定的尺寸提示,让窗口默认大小符合预期,同时给布局设置SetFixedSize约束,阻止布局拉伸窗口。 - 移除固定尺寸策略:去掉
setSizePolicy(Fixed, Fixed),改为允许窗口手动调整,但布局不会自动拉伸。
修改后的完整代码
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)) container = QWidget() layout = QGridLayout() # 设置布局约束:固定布局尺寸,不会因部件自动调整 layout.setSizeConstraint(QLayout.SetFixedSize) 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.size().width() self.windowHeight = self.size().height() self.saveSettings() super().resizeEvent(a0) def sizeHint(self): # 重写尺寸提示,返回保存的窗口尺寸,阻止布局自动调整 return QSize(int(self.windowWidth), int(self.windowHeight)) def loadDefaults(self): config = ConfigParser() config.read('config.ini') try: config.add_section('settings') default_width = int(self.screen().size().width()/2) default_height = int(self.screen().size().height()/2) config['settings']={ 'windowWidth': default_width, 'windowHeight': default_height, } self.windowWidth = default_width self.windowHeight = default_height 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())
说明
- 现在窗口重启后尺寸会准确恢复,不会再出现持续放大的问题。
- 布局被设置为固定尺寸,不会因子部件自动调整窗口大小,但你仍然可以手动拖动窗口边缘调整尺寸,调整后的尺寸会被正确保存。
内容的提问来源于stack exchange,提问作者rllysleepy
相关产品推荐
相关产品推荐

