Search code examples
pythonpyqtpyqt4qstandarditemmodelqstandarditem

Change Text Color of QStandardItem in Model/View?


How do you change the text color of a QStandardItem when used in model/view configuration. It seems that it will always appear as black test.

Below is an executable example code that shows "Hello World" as black text. I'm trying to change it to Green Text.

I've tried using _component.setForeground(QColor(0,255,0)) as well.

import sys
import string
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class ComponentItem(QStandardItem):
    """docstring for ComponentItem"""
    def __init__(self, text, role=Qt.DisplayRole):
        super(ComponentItem, self).__init__()
        self.component = text
        self.role = role

    def data(self, role=Qt.DisplayRole):
        if role != self.role:
            return QVariant()
        if role == Qt.DisplayRole:
            return QVariant(self.component)
        if role == Qt.ForegroundRole:
            return QColor(0,255,0)
        return QVariant()

class ComponentModel(QStandardItemModel):
    """docstring for ComponentModel"""
    def __init__(self, parent=None):
        super(ComponentModel, self).__init__()
        self.parent = parent

        _component = ComponentItem("Hello World")  #How do I change Text Color?
        _component.setData(QColor(255,0,0), Qt.ForegroundRole) #Does not work

        self.appendRow([_component])

class ComponentTree(QTreeView):
    """docstring for ComponentTree"""
    def __init__(self, parent=None):
        super(ComponentTree, self).__init__()
        self.parent = parent

        self.setModel(ComponentModel(self))

class Example(QWidget):
    def __init__(self):
        super(Example, self).__init__()

        _tree = ComponentTree()

        vBox = QVBoxLayout()
        vBox.addWidget(_tree)

        self.setLayout(vBox)
        self.show()

def main():

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

Solution

  • The problem is caused by the following lines:

    if role != self.role:
        return QVariant()
    ...
    

    since if the role is Qt.ForegroundRole and self.role is Qt.DisplayRole then QVariant() is returned and the sentence you want will not be executed.

    I do not understand the reason for maintaining text and role. I do not see the need to overwrite data().

    So the solution would be the following:

    class ComponentItem(QStandardItem):
        def __init__(self, text, role=Qt.DisplayRole):
            super(ComponentItem, self).__init__()
            self.setData(text, role)
    

    enter image description here


    Also another silent error that when I tested your code has been released with the following warnig:

    QObject::startTimer: QTimer can only be used with threads started with QThread
    QObject::startTimer: QTimer can only be used with threads started with QThread
    

    That warning is caused because you have not passed a parent to the model and consequently the memory has not been deleted correctly, the solution is as follows:

    class ComponentModel(QStandardItemModel):
        def __init__(self, parent=None):
            super(ComponentModel, self).__init__(parent)
    
            _component = ComponentItem("Hello World")  #How do I change Text Color?
            _component.setData(QColor(255,0,0), Qt.ForegroundRole) #Does not work
            self.appendRow([_component])