PyQt5 QGridLayout 大小不正确

PyQt5 QGridLayout sizing incorrect

我在 pyqt5 中遇到 QGridLayout 的一些问题。我正在尝试制作一个 GUI,其一侧有一堆按钮,另一侧有一个 table,并且一个图占据了 window 的整个底部。这是我制作的第一个程序,所以我遇到的问题可能比我知道的要多。

我已经在 QTableWidget 中安排了按钮,主要的 QTableWidget 包含几个用户可以在其中输入数据的字段。我希望数据条目 table 的大小大于按钮 table,但是像 中那样调整它的大小答案似乎没有任何作用。无论我输入的 columnSpan 条目如何,按钮 table 都变大了。我做错了什么?

以下是相关的代码位:

class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setGeometry(50, 50, 700, 1000)
        self.home()

    def home(self):
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)

        self.button_table = QTableWidget(self)  
        self.layer_add = QPushButton("Add layer", self)       
        self.plotter = QPushButton("plot transmission", self)

        self.layer_table = QTableWidget(self)

        self.graphWidget = pg.PlotWidget(self)

        self.grid = QGridLayout()
        self.grid.setSpacing(10)
        self.grid.addWidget(self.button_table, 0, 0, 1, 1)
        self.grid.addWidget(self.layer_table, 0, 1, 1, 3)
        self.grid.addWidget(self.graphWidget, 1, 0, 1, 4)      
        self.centralWidget().setLayout(self.grid)
        self.show()

我涂鸦了我理想中希望发生的事情...这是一张图片,上面的代码看起来像什么

用红色标出我希望发生的事情。

编辑:我不明白为什么,如果我将左侧 table 的 QGridLayout columnSpan 设置为 1,右侧 table 设置为 3,左侧table 仍然明显更宽。我愿意学习如何解决这个问题,了解如何使左侧 table 自动缩小到其中按钮的大小,或者其他布局建议。感谢您的帮助!

啊原来在第 1 列上使用 setColumnStretch 解决了这个问题。我还将左边的 table 更改为 QVBoxLayout 并使用 QGridLayout.addLayout 放置它,所以现在一切看起来都更好了

我仍然不太明白为什么 QGridLayout 上的两个 table 宽度不相等,无论选择的列数如何。

虽然您回答了自己的问题,但您似乎通过删除第一个 table 改变了行为(此外,更改第一列拉伸的调整模式与您的问题没有太大关系).所以我正在回答你的 [已编辑] 问题,即使它缺少你将按钮添加到第一个 table.

的部分

主要问题是您为第二个设置的列跨度太大 table:

    self.grid.addWidget(self.button_table, 0, 0, 1, 1)
    self.grid.addWidget(self.layer_table, 0, 1, 1, 3) # <- 3 columns!
    self.grid.addWidget(self.graphWidget, 1, 0, 1, 4)      

在上面的代码中,您告诉布局 layer_table 将具有 3 列的 列跨度 。即使您实际上没有使用三列,通过这样做,布局 认为 第二个 table 将(可能)比第一个占用更多 space。
通常,QGridLayout 将为此使用 columnStretch 属性,但由于默认情况下所有列和行的拉伸均为 0,因此它将使用跨度作为参考。

事实上,使用如下:

    self.grid.addWidget(self.button_table, 0, 0, 1, 1)
    self.grid.addWidget(self.layer_table, 0, 1, 1, 1) # <- 1 column!
    self.grid.addWidget(self.graphWidget, 1, 0, 1, 2)      

与此相同:

    self.grid.addWidget(self.button_table, 0, 0, 1, 1)
    self.grid.addWidget(self.layer_table, 0, 1, 1, 3) # <- 3 columns!
    self.grid.addWidget(self.graphWidget, 1, 0, 1, 4)      
    self.grid.setColumnStretch(0, 1)
    self.grid.setColumnStretch(1, 1)

在第一种情况下,列跨度为 1(一个小部件,一列),并且由于两个小部件属于同一类型,因此它们将使用可用水平空间的一半 space。在第二个中,右侧 table 的列跨度为 3(如您的代码中所示), 第一个 第二列,第三和第四列为 0,这意味着占据第二、第三和第四列的小部件将与占据第一列的小部件具有相同的可用 space,从而获得水平space 在这两个小部件之间平分。

col1 | col2 | col3 | col4
  1  |   1  |   0  |  0

由于第二个 table 占据第 2 至 4 列,因此它的长度为 1 (1 + 0 + 0)。布局使用 Stretches 在小部件之间平均分配 space(考虑它们的大小提示、最小大小提示或它们的 minimum/maximum 大小,无论何时设置):stretches 是求和的整数值,并且然后布局使用总和与这些值之间的比例来调整小部件的大小。


要确保第一个 table 仅使用显示其内容所需的最小值 space,您需要执行以下操作:

  1. sizeAdjustPolicy(这是每个 QAbstractScrollArea 后代的 属性,包括每个项目视图)设置为 AdjustToContents;这将使 table "tell" 的布局大小提示基于其最小内容;
  2. 设置 resize mode of the horizontal header 以将其部分(如 )的 所有 调整为它们的内容;
  3. 将 table 的水平尺寸策略设置为 Maximum;术语 "maximum" 可能违反直觉,但这意味着小部件的大小 不能大于 其大小提示;尽管如此,如果任何其他小部件需要 space(但不小于 minimumSizeHint),它 可能 会缩小,因此,或者,您可以使用 Fixed (这意味着它甚至不能缩小),但如果布局太拥挤并且用户需要使 window 比实际更小,通常最好允许小部件缩小;
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setGeometry(50, 50, 700, 1000)
        self.home()

    def home(self):
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)

        self.button_table = QTableWidget(self)
        self.button_table.setRowCount(3)
        self.button_table.setColumnCount(1)

        # set the sizeHint of the table view (actually, its ancestor class,
        # QAbstractScrollArea) to the minimum size required to show its contents
        self.button_table.setSizeAdjustPolicy(self.button_table.AdjustToContents)

        # set all sections of the horizontal headers to adjust themselves to
        # their contents
        self.button_table.horizontalHeader().setSectionResizeMode(
            QHeaderView.ResizeToContents)

        # get the current sizePolicy and set it to Maximum, meaning that it will
        # use its sizeHint as "maximum": it can expand, but there's no need for
        # that, so if any other sibling widget requires more space, it can use it
        policy = self.button_table.sizePolicy()
        policy.setHorizontalPolicy(policy.Maximum)
        # apply the changed policy
        self.button_table.setSizePolicy(policy)

        self.layer_add = QPushButton("Add layer", self)       
        self.plotter = QPushButton("plot transmission", self)
        # I restored the following lines, which were missing in your edit
        self.button_table.setCellWidget(0, 0, self.layer_add)
        self.button_table.setCellWidget(1, 0, self.plotter)

        self.layer_table = QTableWidget(self)

        self.graphWidget = pg.PlotWidget(self)

        self.grid = QGridLayout()
        self.grid.setSpacing(10)
        self.grid.addWidget(self.button_table, 0, 0, 1, 1)
        self.grid.addWidget(self.layer_table, 0, 1, 1, 1)
        self.grid.addWidget(self.graphWidget, 1, 0, 1, 2)
        self.centralWidget().setLayout(self.grid)

可以看到,现在左边的table只使用了最小的所需宽度,基于水平header宽度(加上垂直header宽度),反过来是基于每列最大宽度的总和。