根据数据更改 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 一起使用,但请记住,从手动调整拆分器大小的那一刻起,它将始终尝试根据新位置保持比例大小。
我一直在尝试让 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 一起使用,但请记住,从手动调整拆分器大小的那一刻起,它将始终尝试根据新位置保持比例大小。