Qt - 不要在 QVBoxLayout 中拉伸小部件

nat*_*sau 2 python qt pyqt5

问题

当我在 Qt 中拖动以调整窗口大小时,它会拉伸 QVBoxLayout 内的小部件。我想避免这种情况。

以下是演示应用程序的几张图片(为此 stackoverflow 帖子创建):

屏幕截图:小部件多于空间(按预期工作 -> 向下滚动以查看内容)

小部件多于空间

屏幕截图:小部件少于空间(问题 - Qt 正在拉伸我的 AccountWidget 项目)

小部件少于空间

如何使用 Qt Layouts 或其他 Qt Widget 类来解决这个问题?这是我的演示应用程序的代码(大约 50 行):

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, \
    QGroupBox, QGridLayout, QLabel, QScrollArea
from typing import List

class AccountWidget(QWidget):
    def __init__(self, data: dict, parent=None):
        super().__init__(parent)        
        self.group_box_layout = QGridLayout()
        for i, (key, value) in enumerate(data.items()):
            self.group_box_layout.addWidget(QLabel(key), i+1, 1)
            self.group_box_layout.addWidget(QLabel(value), i+1, 2)
        self.group_box = QGroupBox()
        self.group_box.setLayout(self.group_box_layout)
        self.main_layout = QVBoxLayout()
        self.main_layout.addWidget(self.group_box)
        self.setLayout(self.main_layout)

class AccountListWidget(QWidget):
    def __init__(self, data: List[dict], parent=None):
        super().__init__(parent)
        self.main_layout = QVBoxLayout()
        for account_data in data:
            self.main_layout.addWidget(AccountWidget(account_data))
        self.setLayout(self.main_layout)

class MainWidget(QWidget):
    def __init__(self, data: List[dict], parent=None):
        super().__init__(parent)
        self.account_list_widget = AccountListWidget(data)
        self.scroll_area = QScrollArea()
        self.scroll_area.setWidgetResizable(True)
        self.scroll_area.setWidget(self.account_list_widget)
        self.main_layout = QVBoxLayout()
        self.main_layout.addWidget(self.scroll_area)
        self.setLayout(self.main_layout)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    data = [{"created":"2019","balance":"100","deposits":"50","type":"Chq"},
            {"created":"2020","balance":"80","deposits":"45","type":"Chq"},
            {"created":"2020","balance":"70","deposits":"55","type":"Sav"}]
    mainWidget = MainWidget(data)
    mainWindow = QMainWindow()
    mainWindow.setCentralWidget(mainWidget)
    mainWindow.setWindowTitle("Demo App")
    mainWindow.resize(300, 300)
    mainWindow.show()
    app.exec()
Run Code Online (Sandbox Code Playgroud)

mus*_*nte 12

只需在布局的底部添加一个拉伸(这仅适用于盒装布局):

class AccountListWidget(QWidget):
    def __init__(self, data: List[dict], parent=None):
        # ...
        self.main_layout.addStretch()
Run Code Online (Sandbox Code Playgroud)

如果您需要在网格布局上执行类似的操作,您可以添加一个 QSpacerItem 或一个空的 QWidget,并将其大小策略设置为展开:

    spacer = QtWidgets.QWidget()
    spacer.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanded)
    gridLayout.addWidget(spacer, gridLayout.rowCount(), 0)
Run Code Online (Sandbox Code Playgroud)

另一个解决方案是为容器设置大小策略(而不是添加拉伸):

class AccountListWidget(QWidget):
    def __init__(self, data: List[dict], parent=None):
        # ...
        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum)
Run Code Online (Sandbox Code Playgroud)

一些建议:

  • 避免使用不必要的容器小部件:您AccountWidget只包含一个 QGroupBox,因此您可能应该只从 QGroupBox 子类化;
  • 与大多数东西一样,网格布局使用基于 0 的索引,因此您的小部件应该从第 0 行和第 0 列(而不是 1)开始添加;如果您这样做是为了增加边距,请使用layout.setContentsMargins;