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

如何调整QGridLayout中被挤压的PyQt5控件数组尺寸?

问题解决:QGridLayout中QLineEdit被挤压的修复

问题描述

我有一个包含QGridLayout的QWidget,其中排布着一组QLineEdit控件。构建该QWidget时,QLineEdit控件会被挤压成窄条,无法正常显示输入区域。需要让控件扩展到正确尺寸,保持紧密排列但不被挤压。

最小可复现示例

import sys

from PySide2.QtWidgets import (
    QScrollArea, QPushButton, QLineEdit, QWidget, QMainWindow, QApplication,
    QVBoxLayout, QGridLayout)

class FaultyWidget(QScrollArea):
    def __init__(self):
        super(FaultyWidget, self).__init__()

        self.push_button = QPushButton("Push")
        self.push_button.clicked.connect(self._loadTextFields)

        self.test_widget = QWidget()
        self.test_widget.setLayout(QGridLayout())
        for i in range(3):
            self.test_widget.layout().addWidget(QLineEdit(), i, 0)

        self.main_widget = QWidget()
        self.main_widget.setLayout(QVBoxLayout())
        self.main_widget.layout().addWidget(self.push_button)
        self.main_widget.layout().addWidget(self.test_widget)

        self.setWidget(self.main_widget)

    def _loadTextFields(self):
        self.test_widget.setParent(None)

        self.test_widget = QWidget()
        self.test_widget.setLayout(QGridLayout())
        for i in range(6):
            self.test_widget.layout().addWidget(QLineEdit(), i, 0)
        self.main_widget.layout().insertWidget(1, self.test_widget)


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setLayout(QVBoxLayout())

        self.main_widget = FaultyWidget()
        self.setCentralWidget(self.main_widget)


if __name__ == "__main__":
    app = QApplication(sys.argv)

    window = MainWindow()
    window.show()

    sys.exit(app.exec_())

修复方案

问题根源在于滚动区域的尺寸适配逻辑、布局的行高策略以及控件的尺寸策略未正确配置。以下是修改后的代码及关键调整点:

修改后的完整代码

import sys

from PySide2.QtWidgets import (
    QScrollArea, QPushButton, QLineEdit, QWidget, QMainWindow, QApplication,
    QVBoxLayout, QGridLayout)

class FixedWidget(QScrollArea):
    def __init__(self):
        super(FixedWidget, self).__init__()
        # 开启滚动区域自动适配内部组件大小
        self.setWidgetResizable(True)

        self.push_button = QPushButton("Push")
        self.push_button.clicked.connect(self._loadTextFields)

        self.test_widget = QWidget()
        self.test_layout = QGridLayout(self.test_widget)
        # 清除布局边距和间距,让控件紧密排列
        self.test_layout.setContentsMargins(0, 0, 0, 0)
        self.test_layout.setSpacing(0)
        
        for i in range(3):
            line_edit = QLineEdit()
            # 设置垂直方向尺寸策略为固定,使用控件自身的建议高度
            line_edit.setSizePolicy(line_edit.sizePolicy().horizontalPolicy(), 
                                   QLineEdit.SizePolicy.Fixed)
            self.test_layout.addWidget(line_edit, i, 0)
            # 强制行高匹配QLineEdit的默认高度
            self.test_layout.setRowMinimumHeight(i, line_edit.sizeHint().height())

        self.main_widget = QWidget()
        self.main_layout = QVBoxLayout(self.main_widget)
        self.main_layout.addWidget(self.push_button)
        self.main_layout.addWidget(self.test_widget)

        self.setWidget(self.main_widget)

    def _loadTextFields(self):
        # 正确移除旧组件,避免布局残留
        self.main_layout.removeWidget(self.test_widget)
        self.test_widget.deleteLater()

        self.test_widget = QWidget()
        self.test_layout = QGridLayout(self.test_widget)
        self.test_layout.setContentsMargins(0, 0, 0, 0)
        self.test_layout.setSpacing(0)
        
        for i in range(6):
            line_edit = QLineEdit()
            line_edit.setSizePolicy(line_edit.sizePolicy().horizontalPolicy(), 
                                   QLineEdit.SizePolicy.Fixed)
            self.test_layout.addWidget(line_edit, i, 0)
            self.test_layout.setRowMinimumHeight(i, line_edit.sizeHint().height())
        
        self.main_layout.insertWidget(1, self.test_widget)
        # 强制更新布局,确保新组件尺寸生效
        self.main_widget.updateGeometry()


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.main_widget = FixedWidget()
        self.setCentralWidget(self.main_widget)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

关键调整说明

  1. 滚动区域适配:给QScrollArea添加setWidgetResizable(True),让滚动区域根据内部内容自动调整组件大小,避免内容被压缩。
  2. 控件尺寸策略:将QLineEdit的垂直方向SizePolicy设为Fixed,确保控件垂直方向使用自身的默认高度,不会被布局强制压缩。
  3. 布局行高控制:给QGridLayout的每一行设置最小高度为对应QLineEdit的建议高度,强制行高适配控件尺寸。
  4. 布局边距优化:清除QGridLayout的边距和间距,让QLineEdit紧密排列,无多余空隙。
  5. 组件移除优化:使用removeWidget和deleteLater()正确清理旧组件,避免布局残留和内存泄漏。
  6. 布局强制更新:添加updateGeometry(),替换组件后强制刷新布局,确保新组件的尺寸设置立即生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 01:55:35