简体   繁体   English

PyQt5 QGridLayout 大小不正确

[英]PyQt5 QGridLayout sizing incorrect

I'm having some issues with QGridLayout in pyqt5.我在 pyqt5 中遇到了 QGridLayout 的一些问题。 I'm trying to make a GUI that has a stack of buttons on one side, a table on the other side, and a plot that occupies the entire bottom of the window.我正在尝试制作一个 GUI,它的一侧有一堆按钮,另一侧有一张桌子,还有一个占据整个窗口底部的图。 This is the first program I've ever made, so I might have more issues than I know.这是我做过的第一个程序,所以我可能遇到的问题比我知道的要多。

I've arranged the buttons within a QTableWidget, and the main QTableWidget contains several fields where users can enter data.我已经在 QTableWidget 中安排了按钮,主要的 QTableWidget 包含几个用户可以输入数据的字段。 I'd like the data entry table to be larger in size than the button table, but resizing it as in this answer doesn't seem to do anything.我希望数据输入表的大小比按钮表大,但是在这个答案中调整它的大小似乎没有任何作用。 The button table is larger no matter the columnSpan entry I put in. What am I doing wrong?无论我输入什么 columnSpan 条目,按钮表都会变大。我做错了什么?

Here are the relevant bits of code:以下是相关的代码位:

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()

I doodled in what I'd ideally like to have happen... here's a picture of what it looks like with the above code我涂鸦了我最希望发生的事情......这是上面代码的样子

and in red what I'd like to have happen.红色的是我希望发生的事情。

Edit: I don't understand why, if I set the QGridLayout columnSpan to be 1 for the table on the left and 3 for the table on the right, the left-hand table is still significantly wider.编辑:我不明白为什么,如果我将左侧表格的 QGridLayout columnSpan 设置为 1,右侧表格的 QGridLayout columnSpan 设置为 3,则左侧表格仍然明显更宽。 I am open to either learning how to fix that, understanding how to make the left-hand table auto-shrink to the size of the buttons within it, or an alternative layout suggestion.我愿意学习如何解决这个问题,了解如何使左侧表格自动缩小到其中的按钮大小,或者提供替代布局建议。 Thanks for any help!谢谢你的帮助!

Ahh turns out that using setColumnStretch on column 1 fixed this problem.啊,原来在第 1 列上使用 setColumnStretch 解决了这个问题。 I also changed the left table to a QVBoxLayout and put it in using QGridLayout.addLayout, so everything looks better now我还将左表更改为 QVBoxLayout 并使用 QGridLayout.addLayout 将其放入,因此现在一切看起来更好

I still don't quite understand why the two tables were unequal widths on QGridLayout though, regardless of the number of columns selected.不管选择的列数如何,我仍然不太明白为什么 QGridLayout 上的两个表的宽度不相等。

While you answered your own question, it seems that you changed the behavior by removing the first table (moreover, changing the resize mode of the first column stretch doesn't have much to do with your issue).当您回答自己的问题时,似乎您通过删除第一个表格来改变行为(此外,更改第一列拉伸的调整大小模式与您的问题没有太大关系)。 So I'm answering to your [edited] question, even if it's missing the part in which you added the buttons to the first table.所以我正在回答您的 [编辑] 问题,即使它缺少您将按钮添加到第一个表格的部分。

The main problem was that you were setting a column span too big for the second 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)      

In the code above, you're telling the layout that the layer_table will have a column span of 3 columns.在上面的代码中,您告诉布局layer_table列跨度为 3 列。 Even if you are not actually using three columns, by doing this the layout thinks that the second table will (probably) occupy more space than the first.即使您实际上没有使用三列,通过这样做,布局也会认为第二个表格(可能)比第一个表格占用更多的空间。
Normally, a QGridLayout will use the columnStretch property for that, but since by default the stretch is 0 for all columns and rows, it will use the span as a reference.通常,QGridLayout 将为此使用columnStretch属性,但由于默认情况下所有列和行的拉伸为 0,因此它将使用跨度作为参考。

In fact, using the following:实际上,使用以下内容:

    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)      

is the same as this:与此相同:

    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)

In the first case, the column span is 1 (one widget, one column), and, since the two widgets are of the same type, they will use half of the available horizontal space.在第一种情况下,列跨度为 1(一个小部件,一列),并且由于两个小部件的类型相同,因此它们将使用可用水平空间的一半。 In the second, the column span of the right table is 3 (as in your code), but the stretch is 1 for both the first and second column, and 0 for the third and fourth, meaning that a widget that occupies the second, third and fourth column will have the same available space than a widget that occupies the first, thus obtaining the horizontal space equally divided between those two widgets.在第二个中,右表的列跨度为 3(如您的代码中所示),第一列第二列的拉伸为 1,第三和第四列的拉伸为 0,这意味着占据第二个的小部件,第三列和第四列将具有与占据第一列的小部件相同的可用空间,从而获得在这两个小部件之间平均划分的水平空间。

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

Since the second table occupies columns 2 to 4, it will have a stretch of 1 (1 + 0 + 0).由于第二个表占据了第 2 到 4 列,因此它的长度为 1 (1 + 0 + 0)。 Stretches are used by layouts to equally divide the space between widgets (considering their size hints, their minimum size hints, or their minimum/maximum size whenever they're set): the stretches are summed integer values, and then the layout uses the proportions between the sum and those values to resize widgets.布局使用伸展来平均划分小部件之间的空间(考虑它们的大小提示、最小大小提示或设置时的最小/最大大小):伸展是整数值的总和,然后布局使用比例在总和和这些值之间调整小部件的大小。


To ensure that the first table uses only the minimum space required to show its contents, you need to do the following:为确保第一个表仅使用显示其内容所需的最小空间,您需要执行以下操作:

  1. set the sizeAdjustPolicy (which is a property of every QAbstractScrollArea descendant, including every item view) to AdjustToContents ;sizeAdjustPolicy (这是每个 QAbstractScrollArea 后代的属性,包括每个项目视图)设置为AdjustToContents this will make the table "tell" the layout that its size hint is based on its minimum contents;这将使表格“告诉”布局其大小提示基于其最小内容;
  2. set the resize mode of the horizontal header to adjust all of its sections (as in columns ) to their contents;设置水平标题调整大小模式以将其所有部分(如列中)调整为它们的内容;
  3. set the horizontal size policy of the table to Maximum ;将表格的水平尺寸策略设置为Maximum the term "maximum" might be counterintuitive, but it means that the widget's size cannot be larger than its size hint;术语“最大”可能违反直觉,但这意味着小部件的大小不能大于其大小提示; still, it could be shrunk if any other widget requires space (but not less than the minimumSizeHint ) so, alternatively, you could use Fixed (meaning that it cannot even shrink), but it's usually better to allow widgets to be shrunk anyway if the layout is too crowded and the user requires to make the window smaller than it is;尽管如此,如果任何其他小部件需要空间(但不小于minimumSizeHint ),它仍然可以缩小,因此,或者,您可以使用Fixed (意味着它甚至不能缩小),但通常最好允许小部件无论如何缩小,如果布局过于拥挤,用户需要将窗口缩小;
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)

As you can see, now the left table only uses the minimum required width, based on the horizontal header width (plus the vertical header width), which in turn is based on the sum of the maximum width of each column.如您所见,现在左表仅使用所需的最小宽度,基于水平标题宽度(加上垂直标题宽度),而后者又基于每列的最大宽度之和。

表格的屏幕截图正确调整到其内容

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM