Milan Soliya
Milan Soliya

Reputation: 55

How to Squeeze the Column to minimum in QTableview in PyQt5?

If I have Table Like as mention Below,

enter image description here

And I want to do as below to squeeze all columns bear to minimum scrollbar size or without scrollbar,

enter image description here

In PyQt5 in QTableview how can I do align any content to center in cell and want to minimum scrollbar and if possible without scrollbar then also it is well good.

as like below image text are not align and I wish to do squeeze all columns as per image 1 and align text to center in PyQt5 in Python.

enter image description here

Upvotes: 0

Views: 788

Answers (1)

musicamante
musicamante

Reputation: 48231

The trick is to use the Stretch resize mode of the horizontal header, which ensures that all columns fit the available size of the view. The only problem comes from the minimumSectionSize(), which by default is a value dependent on the font and the margin between the sort indicator and the text of each header section, so, even using Stretch, the columns wouldn't resize below that width.
By setting the minimum size to 0 we can prevent that behavior. Keep in mind, though, that even with not-so-narrow columns (under 16-18 pixels wide) you will not be able to see the header text at all, no matter if there could be enough space for the text to be shown: some space is always reserved to the header section separators and their margin.

About the text alignment, the standard approach is to use setTextAlignment on each item. If you need to do that constantly, just use a subclass of QStandardItem that automatically sets its alignment after initialization.

from PyQt5 import QtCore, QtGui, QtWidgets

class FitTable(QtWidgets.QTableView):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
        self.horizontalHeader().setMinimumSectionSize(0)

    def resizeEvent(self, event):
        super().resizeEvent(event)
        if not self.model() or not self.model().columnCount():
            return
        # the text can be completely hidden on very narrow columns if the
        # elide mode is enabled; let's disable it for widths lower than
        # the average width of 3 characters
        colSize = self.viewport().width() // self.model().columnCount()
        if colSize < self.fontMetrics().averageCharWidth() * 3:
            self.setTextElideMode(QtCore.Qt.ElideNone)
        else:
            self.setTextElideMode(QtCore.Qt.ElideRight)


class CenteredItem(QtGui.QStandardItem):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setTextAlignment(QtCore.Qt.AlignCenter)


class Window(QtWidgets.QWidget):
    def __init__(self):
        QtWidgets.QWidget.__init__(self)
        layout = QtWidgets.QGridLayout(self)
        self.table = FitTable()
        layout.addWidget(self.table)
        model = QtGui.QStandardItemModel()
        self.table.setModel(model)

        for row in range(5):
            rowItems = []
            for column in range(30):
                # usually the text alignment is manually applied like this:
                # item = QtGui.QStandardItem(str(column + 1))
                #
                # item.setTextAlignment(QtCore.Qt.AlignCenter)
                #
                # for convenience, I use a subclass that automatically does that
                item = CenteredItem(str(column + 1))
                rowItems.append(item)
            model.appendRow(rowItems)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

Upvotes: 2

Related Questions