How should I change just the background color of my tree item using a delegate?
I haven't been able to figure out how to do this without painting on top of the text. In other words, when I use the code below, the color is drawn on top of the text. The text is under the background...
def paint(self, painter, option, index):
MyDelegate.paint(self, painter, option, index)
painter.save()
# set background color
painter.setPen(QPen(Qt.NoPen))
if self.item.is_set and option.state & QStyle.State_Selected:
painter.setBrush(QBrush(QtGui.QColor(100, 200, 0, 200)))
else:
painter.setBrush(QBrush(Qt.NoBrush))
painter.drawRect(option.rect)
painter.restore()
I want to inherit as much as I can.
...
Regarding the comments, I tried to apply the answer " Set color to a QTableView row " ... but I can't seem to get it to work in Python. I'm not sure how the optionV4.backgroundBrush() as any effect. Is the option used by reference so that this change is supposed to be used without a return value?
(These are used without overriding paint
)
def initStyleOption(self, option, index):
print("initStyleOption...")
MyBaseDelegate.initStyleOption(self, option, index)
optionV4 = QtGui.QStyleOptionViewItemV4(option)
optionV4.backgroundBrush = QBrush(QtGui.QColor(100, 200, 100, 200))
I also tried this:
def initStyleOption(self, option, index):
MyBaseDelegate.initStyleOption(self, option, index)
option.backgroundBrush = QBrush(QtGui.QColor(100, 200, 100, 200))
...and this:
def initStyleOption(self, option, index):
option.backgroundBrush = QBrush(QtGui.QColor(100, 200, 100, 200))
MyBaseDelegate.initStyleOption(self, option, index)
And according to the docs, this should not return anything, so I assume option IS passed by reference, which makes sense.
I found another example, which works (though I haven't tried to understand it)
def paint(self, painter, option, index):
option = QtGui.QStyleOptionViewItemV4(option) # Needed for "widget"
self.initStyleOption(option, index) # <--- I did not override this
option.backgroundBrush = QBrush(QtGui.QColor(100, 200, 100, 200))
option.widget.style().drawControl(QStyle.CE_ItemViewItem, option, painter)
ColumnBaseDelegate.paint(self, painter, option, index)
...but the background color is painted over by the selection color. Since I am trying to change the background color when the item is selected, this is a problem. Is there a different brush or method for working with selection colors? I need certain types of items to be a different color.
I tried the answer which demonstrates inverting the selection state before drawing my own background, but it painted an empty background for me for some reason. Putting it in paint worked though...
def paint(self, painter, option, index):
if option.state & QStyle.State_Selected:
option.state &= ~QStyle.State_Selected # Invert state
# This "cast", which is needed to get option.widget, seems to be
# needed for backgroundBrush as well.
option = QtGui.QStyleOptionViewItemV4(option) # Cast for widget
option.backgroundBrush = QBrush(QColor(100, 200, 100, 200))
option.widget.style().drawControl(QStyle.CE_ItemViewItem, option, painter)
super(MyDelegate, self).paint(painter, option, index)
I don't understand why, so I won't add it to an answer at this point.
To override background color for selected items, you can disable the selected flag in
initStyleOption
. For example:Apparently, the background is also painted by
QTreeView.drawRow
before the delegatepaint
function is called, so for indented items, a part of that background keeps the default color.