Reputation: 317
I've been trying to get 2 QTableView widgets to resize with each other in PyQt5. The widgets are in a QComboBox and the layout is set to grid. I tried the resizeColumnToContents method but that just makes the QTableView's columns smaller in width.
How it is currently:
How it should be:
QTableView 1 can have various columns or just one. I want the QTableView 2 to expand in layout so that it covers the entire space and QTableView 1 to be just the one column being displayed. Is there a way to do this? I tried using a splitter and dynamically changing the setstretchfactor, but am not able to implement it. Some clues or hints?
Upvotes: 0
Views: 441
Reputation: 48260
There are two possible solutions.
If you want to use the QSplitter, allowing the user the possibility to resize columns, you could resize the contents after the window has resized. Since tables and splitters might need some time to adjust their sizes, this has to happen after a slight delay (an "event loop" cycle).
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)
Another possibility is to subclass the table and update its sizeHint each time the model contents change. This works by calling updateGeometry()
(which invalidates the sizeHint and tells the parent[s] to compute again sizes) each time the model size changes and the section are resized.
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
To be able to use this class in your UI you'll need to promote the table in Designer:
This approach can also be used with a QSplitter, but remember that, from the moment the splitter is manually resized, it will always try to keep proportional sizes based on the new position.
Upvotes: 1
Reputation: 314
You may want to use: heather = table.horizontalHeader for each column (col) in the table: header.setSectionResizemode(ncol, QHeadedrView.resizeToContents) #This will limit the width of the column. If you want a column to fill all of the available space use "QHeaderView.Stretch" Besides, you may use a QHBoxlayout and perhaps relating the width of both tables.
Upvotes: 0