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,您需要执行以下操作:
- 将
sizeAdjustPolicy
(这是每个 QAbstractScrollArea 后代的 属性,包括每个项目视图)设置为 AdjustToContents
;这将使 table "tell" 的布局大小提示基于其最小内容;
- 设置 resize mode of the horizontal header 以将其部分(如 列 )的 所有 调整为它们的内容;
- 将 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宽度),反过来是基于每列最大宽度的总和。
我在 pyqt5 中遇到 QGridLayout 的一些问题。我正在尝试制作一个 GUI,其一侧有一堆按钮,另一侧有一个 table,并且一个图占据了 window 的整个底部。这是我制作的第一个程序,所以我遇到的问题可能比我知道的要多。
我已经在 QTableWidget 中安排了按钮,主要的 QTableWidget 包含几个用户可以在其中输入数据的字段。我希望数据条目 table 的大小大于按钮 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,您需要执行以下操作:
- 将
sizeAdjustPolicy
(这是每个 QAbstractScrollArea 后代的 属性,包括每个项目视图)设置为AdjustToContents
;这将使 table "tell" 的布局大小提示基于其最小内容; - 设置 resize mode of the horizontal header 以将其部分(如 列 )的 所有 调整为它们的内容;
- 将 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宽度),反过来是基于每列最大宽度的总和。