PyQt5中如何为QSplitter组件设置可调整的初始尺寸?
解决PyQt5中QSplitter组件初始尺寸设置与QSpacerItem失效问题
需求与问题
需要给QSplitter内的组件设置非固定、非最小/最大的初始尺寸:程序启动时右侧红色组件宽度固定为150,同时允许用户自由拖拽调整两边组件大小。但直接使用splitter.setSizes()方法后,左侧组件内的QSpacerItem失效,无法正常占据空间。
初始代码(未设置初始尺寸)
from PyQt5 import QtWidgets import sys app = QtWidgets.QApplication(sys.argv) window = QtWidgets.QWidget() window.resize(800,500) window_layout = QtWidgets.QGridLayout() first_widget = QtWidgets.QScrollArea() first_widget.setStyleSheet("background-color:rgb(0,150,0)") second_widget = QtWidgets.QGroupBox() second_widget.setStyleSheet("background-color:rgb(150,0,0)") splitter = QtWidgets.QSplitter() splitter.addWidget(first_widget) splitter.addWidget(second_widget) window_layout.addWidget(splitter) window.setLayout(window_layout) window.show() app.exec()
存在问题的代码(调用setSizes后Spacer失效)
from PyQt5 import QtWidgets import sys app = QtWidgets.QApplication(sys.argv) window = QtWidgets.QWidget() window.resize(800,500) window_layout = QtWidgets.QGridLayout() first_widget = QtWidgets.QGroupBox() first_widget.setStyleSheet("background-color:rgb(0,150,0)") first_widget_layout = QtWidgets.QGridLayout() first_widget_spacer_0 = QtWidgets.QSpacerItem(100000,0,QtWidgets.QSizePolicy.Expanding,QtWidgets.QSizePolicy.Maximum) first_widget_layout.addItem(first_widget_spacer_0) first_widget.setLayout(first_widget_layout) second_widget = QtWidgets.QGroupBox() second_widget.setStyleSheet("background-color:rgb(150,0,0)") splitter = QtWidgets.QSplitter() splitter.addWidget(first_widget) splitter.addWidget(second_widget) splitter.setSizes([window.width() - 150, 150]) window_layout.addWidget(splitter) window.setLayout(window_layout) window.show() app.exec()
解决方案
问题根源在于:
splitter.setSizes()调用时机过早,此时窗口和内部布局尚未完成尺寸计算,强制设置尺寸会干扰内部布局逻辑,导致QSpacerItem失效- QSpacerItem的初始尺寸设置过大,超出布局计算范围
修正后的代码如下:
from PyQt5 import QtWidgets, QtCore import sys app = QtWidgets.QApplication(sys.argv) window = QtWidgets.QWidget() window.resize(800,500) window_layout = QtWidgets.QGridLayout() # 左侧组件 first_widget = QtWidgets.QGroupBox() first_widget.setStyleSheet("background-color:rgb(0,150,0)") first_widget_layout = QtWidgets.QGridLayout() # 调整Spacer初始尺寸为0,依赖Expanding策略占据空间 first_widget_spacer_0 = QtWidgets.QSpacerItem( 0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Maximum ) first_widget_layout.addItem(first_widget_spacer_0) first_widget.setLayout(first_widget_layout) # 右侧组件 second_widget = QtWidgets.QGroupBox() second_widget.setStyleSheet("background-color:rgb(150,0,0)") splitter = QtWidgets.QSplitter() splitter.addWidget(first_widget) splitter.addWidget(second_widget) window_layout.addWidget(splitter) window.setLayout(window_layout) window.show() # 延迟设置Splitter尺寸,确保布局已完成计算 def set_splitter_sizes(): splitter.setSizes([window.width() - 150, 150]) QtCore.QTimer.singleShot(0, set_splitter_sizes) app.exec()
关键说明
- 使用
QTimer.singleShot(0, ...):将尺寸设置操作延迟到事件循环初始化完成后执行,此时窗口和内部布局的尺寸已确定,不会破坏内部布局逻辑 - 调整QSpacerItem初始尺寸:将宽高设为0,利用
Expanding的尺寸策略让它自动占据左侧组件的可用空间,避免过大的初始值干扰布局计算
内容的提问来源于stack exchange,提问作者Mohammed almalki
相关产品推荐
相关产品推荐

