1

I have a QTreeWidget that has values in them, which I only want to show a certain number of decimals but keep the precision for calculation purposes. I have it working correctly, but the highlighting of the selected items are messed up and show white around the cell that has been drawn.

How can I fix the highlighting so that is solid blue for the entire row?

class InitialDelegate(QtWidgets.QItemDelegate):
    'Changes number of decimal places in gas analysis self.chosen table'
    def __init__(self, decimals, parent=None):
        super().__init__(parent)
        self.nDecimals = decimals
    def paint(self, painter, option, index):
        if index.column() == 1:
            value = index.model().data(index, QtCore.Qt.DisplayRole)
            try:
                number = float(value)
                painter.drawText(option.rect, QtCore.Qt.AlignCenter , "{:.{}f}".format(number, self.nDecimals))
            except:
                QtWidgets.QItemDelegate.paint(self, painter, option, index)
        else:
            QtWidgets.QItemDelegate.paint(self, painter, option, index)

This is what it produces:

enter image description here

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Drees
  • 688
  • 1
  • 6
  • 21

1 Answers1

2

I have 2 observations in its implementation:

  • If you only want to change what the format as the text is shown then you should not override the paint() method since it not only paints the text but also the background, icons, etc. The drawDisplay() method must be override.

  • If you are only going to apply the change to a column it is better to set the delegate using the setItemDelegateForColumn() method

Considering the above, then the solution is:

from PyQt5 import QtCore, QtGui, QtWidgets


class InitialDelegate(QtWidgets.QItemDelegate):
    "Changes number of decimal places in gas analysis self.chosen table"

    def __init__(self, decimals, parent=None):
        super().__init__(parent)
        self.nDecimals = decimals

    def drawDisplay(self, painter, option, rect, text):
        option.displayAlignment = QtCore.Qt.AlignCenter
        try:
            number = float(text)
            text = "{:.{}f}".format(number, self.nDecimals)
        except:
            pass
        super().drawDisplay(painter, option, rect, text)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = QtWidgets.QTreeWidget(columnCount=3)
    delegate = InitialDelegate(2, w)
    w.setItemDelegateForColumn(1, delegate) # <---
    w.setHeaderLabels(["Gas Component", "Molecular Weight", "Mol%"])
    it = QtWidgets.QTreeWidgetItem(["Hexane", "86.1777", ""])
    w.addTopLevelItem(it)
    w.show()
    sys.exit(app.exec_())

Plus:

If you want to do the same but using QStyledItemDelegate then the solution is override initStyleOption():

class InitialDelegate(QtWidgets.QStyledItemDelegate):
    "Changes number of decimal places in gas analysis self.chosen table"

    def __init__(self, decimals, parent=None):
        super().__init__(parent)
        self.nDecimals = decimals

    def initStyleOption(self, option, index):
        super().initStyleOption(option, index)
        option.displayAlignment = QtCore.Qt.AlignCenter
        try:
            text = index.model().data(index, QtCore.Qt.DisplayRole)
            number = float(text)
            option.text = "{:.{}f}".format(number, self.nDecimals)
        except:
            pass
eyllanesc
  • 235,170
  • 19
  • 170
  • 241