You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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())

问题分析

  1. 尺寸保存错误:frameGeometry()获取的是包含窗口边框、标题栏的整体尺寸,但resize()设置的是窗口客户区(不含边框)的尺寸,每次保存的尺寸比实际需要的客户区大,重启后叠加边框导致窗口越来越大。
  2. 布局自动拉伸:默认布局会根据子部件的最小尺寸调整窗口,需要限制布局的尺寸约束。

解决方案

关键修改点

  1. 替换尺寸获取方式:用self.size()获取客户区尺寸,保存和加载都使用这个值,避免边框带来的误差。
  2. 重写sizeHint():返回固定的尺寸提示,让窗口默认大小符合预期,同时给布局设置SetFixedSize约束,阻止布局拉伸窗口。
  3. 移除固定尺寸策略:去掉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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 08:57:39