Skip to content
Advertisement

PyQt QTableView resizeRowsToContents not completely resize on initialisation

I have a minimum example here of a QTableView widget that displays a long string that I want word wrapped when I start the app.

from PyQt6.QtWidgets import (
    QMainWindow,
    QTableView,
    QHeaderView,
    QApplication,
)
from PyQt6.QtCore import (
    Qt, 
    QEvent,
    QAbstractTableModel,
    QSize,
    QEvent
)
import sys

text = """A long string which needs word wrapping to fully display. A long string which needs word wrapping to fully display. A long string which needs word wrapping to fully display."""

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        
        self.table = QTableView()
        header = self.table.horizontalHeader()
        header.setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
        
        self.table.horizontalHeader().sectionResized.connect(self.table.resizeRowsToContents)
        
        self.model = TableModel([[text] for i in range(50)])
        self.table.setModel(self.model)
        self.setCentralWidget(self.table)
        
        self.table.resizeRowsToContents()

    def changeEvent(self, event):
        if event.type() == QEvent.Type.WindowStateChange: 
            self.table.resizeRowsToContents()

        return super(MainWindow, self).changeEvent(event)

class TableModel(QAbstractTableModel):
    def __init__(self, data):
        super().__init__()
        self._data = data

    def data(self, index, role):
        if role == Qt.ItemDataRole.DisplayRole:
            return self._data[index.row()][index.column()]

    def rowCount(self, index):
        return len(self._data)

    def columnCount(self, index):
        return len(self._data[0])

app = QApplication(sys.argv)
app.lastWindowClosed.connect(app.quit)
w = MainWindow()
w.show()
app.exec()

When I run the above I get this

enter image description here

but when I resize the window manually just slightly, I get what I’m expecting

enter image description here

How would I get the second image as the state when the app is started? I thought calling self.table.resizeRowsToContents() in the __init__ method would do it. Another question is, why does self.table.horizontalHeader().sectionResized.connect(self.table.resizeRowsToContents) work upon resizing when resizeRowsToContents() does not work in the __init__ method?

Advertisement

Answer

why does self.table.horizontalHeader().sectionResized.connect(self.table.resizeRowsToContents) work upon resizing when resizeRowsToContents() does not work in the init method?

Because the window isn’t rendered yet, that’s why the QTableView doesn’t know yet how big the text is in order to resize the rows.

How would I get the second image as the state when the app is started? I thought calling self.table.resizeRowsToContents() in the init method would do it.

You could separate the population of the table from the init method, or delay it, until Your widget is rendered, preferably inside the class itself, but you can do something like this:

# ...
app = QApplication(sys.argv)
app.lastWindowClosed.connect(app.quit)
w = MainWindow()
w.show()
w.table.resizeRowsToContents() # I just added this line
app.exec()
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement