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

PyQt5中QGridLayout的setRowStretch不生效问题如何解决

问题描述

在PyQt5中使用QGridLayout布局开发计算器GUI时,调用setRowStretch()方法想要实现按钮行的垂直拉伸效果,但方法始终没有达到预期,而同布局下的setColumnStretch()方法可以正常工作。

复现代码
import PyQt5.QtWidgets as qtw
import PyQt5.QtGui as qtg
import PyQt5.QtCore as qtcore

class MainWindow(qtw.QWidget):
    def __init__(self):
        super().__init__()
        # Add a title
        self.setWindowTitle('Calculator - Anh Nguyen')
        
        
        # Create a label
        my_label = qtw.QLabel("0")
        # Set background color
        my_label.setStyleSheet("background-color: #e3e1da;\
                                border: 1px solid black")
        
        my_label.setMaximumHeight(50)
        
        # Align label text
        my_label.setAlignment(qtcore.Qt.AlignmentFlag.AlignVCenter | qtcore.Qt.AlignmentFlag.AlignRight)        
        
        my_label.setFont(qtg.QFont('Helvetica', 20))
        
        # Add grid layout for calculator buttons
        main_gridlayout = qtw.QGridLayout()
        
        main_gridlayout.addWidget(my_label, 0, 0, 1, 4)
        main_gridlayout.addWidget(qtw.QPushButton('%'), 1, 0)
        main_gridlayout.addWidget(qtw.QPushButton('CE'), 1, 1)
        main_gridlayout.addWidget(qtw.QPushButton('C'), 1, 2)
        main_gridlayout.addWidget(qtw.QPushButton('BKSP'), 1, 3)
        main_gridlayout.addWidget(qtw.QPushButton('7'), 2, 0)
        main_gridlayout.addWidget(qtw.QPushButton('8'), 2, 1)
        main_gridlayout.addWidget(qtw.QPushButton('9'), 2, 2)
        main_gridlayout.addWidget(qtw.QPushButton('/'), 2, 3)
        main_gridlayout.addWidget(qtw.QPushButton('4'), 3, 0)
        main_gridlayout.addWidget(qtw.QPushButton('5'), 3, 1)
        main_gridlayout.addWidget(qtw.QPushButton('6'), 3, 2)
        main_gridlayout.addWidget(qtw.QPushButton('-'), 3, 3)
        main_gridlayout.addWidget(qtw.QPushButton('1'), 4, 0)
        main_gridlayout.addWidget(qtw.QPushButton('2'), 4, 1)
        main_gridlayout.addWidget(qtw.QPushButton('3'), 4, 2)
        main_gridlayout.addWidget(qtw.QPushButton('+'), 4, 3)
        main_gridlayout.addWidget(qtw.QPushButton('+/-'), 5, 0)
        main_gridlayout.addWidget(qtw.QPushButton('0'), 5, 1)
        main_gridlayout.addWidget(qtw.QPushButton('.'), 5, 2)
        main_gridlayout.addWidget(qtw.QPushButton('='), 5, 3)
        
        # This is NOT working:
        main_gridlayout.setRowStretch(1,1)
        
        # This is working
        main_gridlayout.setColumnStretch(2,1)
        
        
        
        self.setLayout(main_gridlayout)
        
        self.show()
        
app = qtw.QApplication([])
mw = MainWindow()

app.exec_()
问题原因

setRowStretch()方法本身没有故障,视觉上不生效是两个PyQt5布局默认规则共同导致的:

  • QPushButton默认的垂直大小策略为QSizePolicy.Fixed:该策略下按钮的高度会固定为自身推荐高度(sizeHint返回值),就算布局给所在行分配了更多垂直空间,按钮也不会主动拉伸占满空间,只会保持原有高度居中显示,看起来就像行拉伸没有生效。
  • 拉伸因子设置范围不对:代码中仅给索引为1的按钮行设置了拉伸因子1,其余4行按钮所在行(索引2-5)的拉伸因子默认是0,就算拉伸规则生效,窗口的多余垂直空间也只会全部分配给第1行,其余按钮行依然保持原有高度。
  • setColumnStretch()能正常工作的原因是QPushButton默认水平大小策略为QSizePolicy.Preferred,允许水平方向拉伸填满分配到的列空间。
修复方案

如果需要所有按钮行均匀占满显示标签下方的全部垂直空间、按钮自动拉伸填满对应行,做两处修改即可:

  1. 给所有按钮行(索引1到5)设置相同的拉伸因子,让各行按比例平分多余垂直空间
  2. 将所有按钮的垂直大小策略改为QSizePolicy.Expanding,允许按钮跟随行的分配空间拉伸高度

替换原有设置拉伸的代码片段即可:

# 给1-5行的按钮行设置相同拉伸因子,均匀分配垂直空间
for row_idx in range(1, 6):
    main_gridlayout.setRowStretch(row_idx, 1)

# 遍历布局内所有控件,将按钮的大小策略改为双向可扩展
for i in range(main_gridlayout.count()):
    item = main_gridlayout.itemAt(i)
    w = item.widget()
    if isinstance(w, qtw.QPushButton):
        w.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.Expanding)

如果只需要某一行单独占用多余垂直空间,只给对应行设置拉伸因子,同时修改该行内按钮的垂直大小策略即可。


内容的提问来源于stack exchange,提问作者Ryan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 12:36:27