Multiple selection colors in a QTreeWidget
-
I am trying to create a QTreeWidget that uses a single highlight color for all but the last selection. I been fighting this problem for 2 months now and cannot come up with a solution. I am using PySide2 in Maya 2019.
I tried using style sheet but that is global to all selected rather than individual QTreeWidgetItems.
Each time I am able to change the color for each selection. The window remembers the old color and creates an overlap. Once I select a different element in Maya my GUI corrects the colors.
I tried using a delegate show in my example code. My recent attempt is overriding the drawRow but with the same results.
from PySide2 import QtCore from PySide2 import QtWidgets from PySide2 import QtGui class TestDialog(QtWidgets.QDialog): def __init__(self): super(TestDialog, self).__init__() self.setWindowTitle("Test Dialog") self.setMinimumWidth(200) self.tree = TreeWidget() # Change all the highlighted items to the same color # palette = QtGui.QPalette() # palette.setColor(QtGui.QPalette.Highlight, QtGui.QColor(93, 93, 93)) # self.tree.setPalette(palette) main_layout = QtWidgets.QVBoxLayout(self) main_layout.addWidget(self.tree) colors = ['red', 'green', 'blue', 'purple', 'black'] parent = self.tree for color in colors: parent = TreeWidgetItem(parent, color) self.tree.expandAll() class TreeWidget(QtWidgets.QTreeWidget): def __init__(self): super(TreeWidget, self).__init__() self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) self.setIndentation(10) self.setColumnCount(2) self.header().resizeSection(1, 28) self.header().swapSections(1, 0) self.setHeaderHidden(True) css = """ QTreeView::item:selected { background-color: grey; } """ # self.setStyleSheet(css) delegate = MyDelegate(None, self) self.setItemDelegate(delegate) class TreeWidgetItem(QtWidgets.QTreeWidgetItem): def __init__(self, parent, label): super(TreeWidgetItem, self).__init__(parent) self.setText(0, label) self.lockBox_cb = QtWidgets.QCheckBox() self.treeWidget().setItemWidget(self, 1, self.lockBox_cb) class MyDelegate(QtWidgets.QStyledItemDelegate): def __init__(self, parent, tree): super(MyDelegate, self).__init__(parent) self.tree = tree def paint(self, painter, option, index): column = index.column() row = index.row() item = self.tree.itemFromIndex(index) currentItem = self.tree.currentItem() brush = QtGui.QBrush(QtCore.Qt.transparent) painter.setBrush(brush) painter.fillRect(option.rect, brush) if column == 0: if option.state & QtWidgets.QStyle.State_Selected: if id(currentItem) == id(item): brush = QtGui.QBrush(QtGui.QColor(102, 40, 178, 255)) else: brush = QtGui.QBrush(QtGui.QColor(226, 131, 255, 255)) option.palette.setBrush(QtGui.QPalette.Highlight, brush) option_copy = QtWidgets.QStyleOptionViewItem(option) option_copy.rect.setLeft(0) option_copy.backgroundBrush = brush self.tree.style().drawPrimitive(QtWidgets.QStyle.PE_PanelItemViewItem, option_copy, painter) super(MyDelegate, self).paint(painter, option, index) if __name__ == "__main__": d = TestDialog() d.show()
The drawRow method in my main code. So, this won't work in my example:
def drawRow(self, painter, option, index): item = self.itemFromIndex(index) currentItem = self.currentItem() if str(item.pyNode) in self.selected: if str(item.pyNode) == str(currentItem.pyNode): brush = QtGui.QBrush(QtGui.QColor(102, 40, 178, 255)) else: brush = QtGui.QBrush(QtGui.QColor(226, 131, 255, 255)) painter.fillRect(option.rect, brush) super(JointTreeWidget, self).drawRow(painter, option, index)
Selecting the items shows both colors
After "refreshing" the GUI by selecting a different window element in Maya. The colors fix themselves
Thanks
-
Hi and welcome to devnet,
What version of PySide2 are you using ?
Do you also have that if you generate that widget in a standalone application ?