0lan
0lan

Reputation: 229

Disable the sort arrow in a specific column in QTableWidget with PyQt/PySide

I would like to remove the arrow from the first column heading so the title is centered with the checkboxes. All of this without disabling the possibility to sort the column.

This is my current code.

import sys

from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
    QApplication,
    QProxyStyle,
    QStyle,
    QTableWidget,
    QTableWidgetItem,
)


class ProxyStyle(QProxyStyle):
    def subElementRect(self, e, opt, widget):
        r = super().subElementRect(e, opt, widget)
        if e == QStyle.SE_ItemViewItemCheckIndicator:
            r.moveCenter(opt.rect.center())
        return r


class Table(QTableWidget):
    def __init__(self):
        QTableWidget.__init__(self, 3, 1)
        self._style = ProxyStyle(self.style())
        self.setStyle(self._style)
        for i in range(self.rowCount()):
            for j in range(self.columnCount()):
                it = QTableWidgetItem()
                self.setItem(i, j, it)
                it.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
                it.setCheckState(Qt.Checked if (i + j) % 2 == 0 else Qt.Unchecked)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = Table()
    w.show()
    sys.exit(app.exec_())

Upvotes: 0

Views: 1288

Answers (1)

musicamante
musicamante

Reputation: 48260

The simplest solution is to override the drawControl() and set the indicator of the QStyleOptionHeader to 0 if the column matches the one you want to hide.

class ProxyStyle(QProxyStyle):
    # ...
    def drawControl(self, ctl, opt, qp, widget=None):
        if ctl == QStyle.CE_HeaderSection and opt.orientation == Qt.Horizontal:
            if opt.section == widget.parent().property('hideSortIndicatorColumn'):
                opt.sortIndicator = 0
        super().drawControl(ctl, opt, qp, widget)


class Table(QTableWidget):
    def __init__(self):
        # ...
        self.setProperty('hideSortIndicatorColumn', 0)

Be aware that setting the style on a widget is not always enough for complex widgets that have children.
In your case it works because you added the current style to the proxy constructor, but this means that the ownership of the style will be completely taken by the proxy, and any other QWidget will use the proxy from that moment on (which is almost the same as setting the proxy to the whole application).
The alternative is to create the proxy without any argument (in this case a new instance of the default native style will be used), but that also means that no children of the widget will inherit the style, since QStyles are not propagated to their children.

Upvotes: 1

Related Questions