如何获取PyQt5中QGridLayout内扩展部件的size hint?
在QGridLayout中确定部件尺寸及获取布局后实际尺寸的方法
核心问题说明
你提到的sizeHint()是部件自身的推荐最小尺寸,和布局后实际显示的尺寸完全是两回事。布局会根据以下规则调整部件尺寸:
- 部件的
sizePolicy设置(比如Button4的MinimumExpanding垂直策略) - 部件在布局中跨的行列数(比如Button5跨2列、Button4跨3行)
- 布局的拉伸因子(你设置的
setRowStretch和setColumnStretch) - 父窗口的可用空间
所以即使三个按钮的sizeHint相同,布局后实际尺寸必然不同。
获取布局后实际尺寸的正确方式
要拿到部件在布局中最终显示的尺寸,必须等布局完成计算后再获取,以下是几种可行方法:
方法1:在窗口show之后延迟获取
刚调用show()时布局可能还没完成,用QTimer延迟一点时间再获取:
from PyQt5.QtWidgets import * from PyQt5.QtCore import QTimer class Widget(QWidget): def __init__(self): super().__init__() self.setWindowTitle("QGridlayout") self.btn1 = QPushButton("Button_1") self.btn2 = QPushButton("Button_2") self.btn3 = QPushButton("Button_3") self.btn4 = QPushButton("Button_4") self.btn4.setSizePolicy(QSizePolicy.Minimum,QSizePolicy.MinimumExpanding) self.btn5 = QPushButton("Button_5") self.btn6 = QPushButton("Button_6") self.btn7 = QPushButton("Button_7") self.btn8 = QPushButton("Button_8") self.btn9 = QPushButton("Button_9") self.gl = QGridLayout() self.gl.addWidget(self.btn1,0,0,1,1) self.gl.addWidget(self.btn2,0,1,1,1) self.gl.addWidget(self.btn3,0,2,1,1) self.gl.addWidget(self.btn4,0,3,3,1) self.gl.addWidget(self.btn5,1,0,1,2) self.gl.addWidget(self.btn6,2,0,1,3) self.gl.addWidget(self.btn7,3,0,1,4) self.gl.addWidget(self.btn8,1,2,1,1) self.gl.setRowStretch(4,1) self.gl.setColumnStretch(2,1) self.setLayout(self.gl) # 添加定时器,延迟获取尺寸 QTimer.singleShot(100, self.getActualSizes) def getActualSizes(self): print("Button1实际尺寸:", self.btn1.size()) print("Button4实际尺寸:", self.btn4.size()) print("Button5实际尺寸:", self.btn5.size()) if __name__ == '__main__': import sys app = QApplication(sys.argv) w = Widget() w.show() sys.exit(app.exec_())
方法2:重写resizeEvent事件
每次窗口尺寸变化(布局重新计算)时自动获取:
class Widget(QWidget): def __init__(self): super().__init__() self.setWindowTitle("QGridlayout") # 原按钮初始化和布局代码不变... self.setLayout(self.gl) def resizeEvent(self, event): super().resizeEvent(event) # 布局完成后获取尺寸 print("Button1实际尺寸:", self.btn1.size()) print("Button4实际尺寸:", self.btn4.size()) print("Button5实际尺寸:", self.btn5.size())
方法3:强制触发布局计算后获取
如果不想等窗口show,可手动激活布局后获取,但要确保父窗口已经初始化:
class Widget(QWidget): def __init__(self): super().__init__() # 原按钮初始化和布局代码不变... self.setLayout(self.gl) # 强制布局计算 self.gl.activate() # 此时可获取尺寸 print("Button1实际尺寸:", self.btn1.size()) print("Button4实际尺寸:", self.btn4.size()) print("Button5实际尺寸:", self.btn5.size())
补充说明
- 如果你需要的是布局为部件分配的可用空间(不包含边框等),可以用
widget.contentsRect().size() sizeHint()永远是部件自身的推荐尺寸,不会因为布局而改变,所以你要的"扩展后size hint"其实就是布局后的实际尺寸
内容的提问来源于stack exchange,提问作者Bala
相关产品推荐
相关产品推荐

