根据数据更改 QTableView 小部件的水平大小

Change QTableView widgets horizontal size based on data

我一直在尝试让 2 个 QTableView 小部件在 PyQt5 中相互调整大小。小部件位于 QComboBox 中,布局设置为网格。我尝试了 resizeColumnToContents 方法,但这只会使 QTableView 的列宽度变小。

目前情况:

应该如何:

QTableView 1 可以有多个列或只有一个。我希望 QTableView 2 在布局中展开,以便它覆盖整个 space 并且 QTableView 1 只是显示的一列。有没有办法做到这一点?我尝试使用拆分器并动态更改 setstretchfactor,但无法实现它。一些线索或提示?

您可能想使用: 石南花 = table.horizontalHeader 对于 table 中的每一列 (col): header.setSectionResizemode(ncol, QHeadedrView.resizeToContents) #这将限制 列的宽度。如果你想要一个列来填充所有可用的 space 使用 "QHeaderView.Stretch" 此外,您可以使用 QHBoxlayout 并可能关联两个 table 的宽度。

有两种可能的解决方案。

如果您想使用 QSplitter,允许用户调整列的大小,您可以在 window 调整大小后调整内容的大小。由于 tables 和拆分器可能需要一些时间来调整它们的大小,因此这必须在稍有延迟("event loop" 周期)后发生。

class Test(QtWidgets.QMainWindow):
    # ...
    def delaySplitterResize(self):
        if not self.model1.columnCount():
            return
        total = self.table1.width() + self.table2.width()
        leftWidth = self.table1.frameWidth() * 2 + self.table1.contentsMargins().left() * 2
        for s in range(self.model1.columnCount()):
            leftWidth += self.table1.horizontalHeader().sectionSize(s)
        self.splitter.setSizes([leftWidth, total - leftWidth])

    def resizeEvent(self, event):
        super().resizeEvent(event)
        QtCore.QTimer.singleShot(0, self.delaySplitterResize)

另一种可能性是子class table 并在每次模型内容更改时更新其 sizeHint。这通过调用 updateGeometry()(它使 sizeHint 无效并告诉父 [s] 再次计算大小)来实现,每次模型大小更改和部分调整大小时。

class MinimumSizeTable(QtWidgets.QTableView):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # an explicit minimum size is recommended
        self.setMinimumWidth(self.horizontalHeader().defaultSectionSize())
        # ensure that the widget tries to occupy only the width provided
        # by the sizeHint
        self.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
        # section resizing requires some time to "update" the section hints,
        # so we need to delay the call to updateGeometry
        self.horizontalHeader().sectionResized.connect(lambda: QtCore.QTimer.singleShot(0, self.updateGeometry))
        self.verticalHeader().sectionResized.connect(lambda: QtCore.QTimer.singleShot(0, self.updateGeometry))

    def setModel(self, model):
        if self.model():
            self.model().columnsInserted.disconnect(self.updateGeometry)
            self.model().columnsRemoved.disconnect(self.updateGeometry)
        super().setModel(model)
        if self.model():
            self.model().columnsInserted.connect(self.updateGeometry)
            self.model().columnsRemoved.connect(self.updateGeometry)
        self.updateGeometry()

    def sizeHint(self):
        hint = super().sizeHint()
        if not self.model() or not self.model().columnCount():
            hint.setWidth(self.horizontalHeader().defaultSectionSize())
        else:
            width = self.frameWidth() * 2 + self.contentsMargins().left() * 2
            for s in range(self.model().columnCount()):
                width += self.horizontalHeader().sectionSize(s)
            hint.setWidth(width)
        return hint

为了能够在您的 UI 中使用此 class,您需要 提升 Designer 中的 table:

  • 右键单击 table 和 select "Promote to"
  • 在 "Promoted class name" 字段中键入子class 名称
  • 在"Header file"字段
  • 中键入包含子class但不带扩展名(例如"mytable")的python文件
  • 单击 "Add",然后单击 "Promote",然后保存。

这种方法也可以与 QSplitter 一起使用,但请记住,从手动调整拆分器大小的那一刻起,它将始终尝试根据新位置保持比例大小。