QTreeView 中节点的 setStyleSheet 或 QStyledItemDelegate

setStyleSheet or QStyledItemDelegate for a node in QTreeView

我正在尝试更改 QTreeView 中特定节点的图标。节点将使用 QCheckbox,并且根据应用程序逻辑,一些节点将改为使用其他图标表示节点 selected/unselected 状态。

下面的示例显示了如何为整个树设置样式表,但我认为我不能为树中的单个节点设置样式表。

#Based on 
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtGui, QtCore

class Window(QtGui.QWidget):
    changeStyleTriggered = QtCore.pyqtSignal()

    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.createTree()
        self.connectSlots()

    def createTree(self):
        data = ['A', 'B', 'C', 'D', 'E', 'F']
        model = MyTreeView(data)
        self.treeView = QTreeView()
        self.treeView.setModel(model)
        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.treeView)
        self.changeIconPushButton = QtGui.QPushButton("Change a single icon")
        layout.addWidget(self.changeIconPushButton)
        self.setLayout(layout)

    def fireChangeStyleSignal(self):
        self.changeStyleTriggered.emit()

    @pyqtSlot()
    def changeStyleSignal(self):
        print(">>changeStyleSignal()")
        self.setStyleSheet("QTreeView::indicator:unchecked {image: url(:/icons/image.png);}")

    def connectSlots(self):
        self.changeStyleTriggered.connect(self.changeStyleSignal)
        self.changeIconPushButton.clicked.connect(self.fireChangeStyleSignal)

class TestItem():
    def __init__(self, name, checked):
        self.checked = checked
        self.name = name

class MyTreeView(QAbstractListModel):
    def __init__(self, args, parent=None):
        super(StbTreeView, self).__init__(parent)

        self.args = []
        for item_name in args:
            self.args.append(TestItem(item_name, False))

        for item in self.args:
            print (item.name)

    def rowCount(self, parent):
        return len(self.args)

    def headerData(self, section, orientation, role):
        if role == Qt.DisplayRole:
            if orientation == Qt.Horizontal:
                return "Nodes"

    def flags(self, index):
        return  Qt.ItemIsUserCheckable | Qt.ItemIsEditable | Qt.ItemIsSelectable | Qt.ItemIsEnabled

    def data(self, index, role=Qt.DisplayRole):
        if role == Qt.DisplayRole:
            row = index.row()
            print (self.args[row].name)
            return self.args[row].name

        if role == Qt.CheckStateRole:
            row = index.row()
            print (self.args[row].checked)
            if self.args[row].checked == False:
                return Qt.Unchecked
            else:
                return Qt.Checked

    def setData(self, index, value, role):
        if role == Qt.CheckStateRole:
            row = index.row()
            self.args[row].checked = not self.args[row].checked             
        return True

def main():
    myapp = QApplication(sys.argv)

    window = Window()
    window.show()
    myapp.exec_()

if __name__ == '__main__':
    main()

另一种选择是使用 QStyledItemDelegate。下面是一个小的class来改变字体,但是我还没有弄清楚如何用delegate改变单个图标。

class BoldDelegate(QtGui.QStyledItemDelegate):
    def paint(self, painter, option, index):
        option.font.setWeight(QtGui.QFont.Bold)
        QtGui.QStyledItemDelegate.paint(self, painter, option, index)

并使用它 运行 这个(例如在 QTreeView 的 @pyqtSlot() 中):

self.setItemDelegate(BoldDelegate(self))

有什么想法吗?

A QCheckBox 不使用图标来显示其状态。您应该首先创建一个项目,在该项目中,您可以通过任何方式获得一个按您希望的方式运行的小部件,具有正确的 checked/unchecked 外观。

完成后,您将让您的代表根据模型数据项的某些 属性 创建此类项。例如,您可能有一个自定义角色,它向您的委托人指示应该使用非默认小部件 class 来编辑项目。