Alan Alan - 1 year ago 165
Python Question

PyQt Tableview row background colour based on cell value

Python (3+) and Qt (5) (although happy to have Py2.7 and Qt4 answers!).
Totally confused by vast documentation about styles, delegates, models and everything else.

I've found it simple to set the background of alternate rows but I want to set the background for rows where one column matches a specific value (i.e.

Archive == True
).

Alternate rows:

self.plainModel = QSqlQueryModel()
self.create_model()
self.linksTable.setModel(self.plainModel)
self.linksTable.setAlternatingRowColors(True)
self.linksTable.setStyleSheet("alternate-background-color: Lightgrey;background-color: white;")
self.linksTable.resizeColumnsToContents()


I've seen an example showing how to do it through the model but this specific example seems to be simply replicating the alternate rows outcome, and after a few days staring a code I can't work out how to translate that to checking the archive column.

Extract from example:

elif role == Qt.BackgroundRole:
if index.row() % 2 == 0:
return QBrush(Qt.yellow)
elif role != Qt.DisplayRole:
return QVariant()


I've found another example using delegates but can't at the moment get my head around it.

Especially I still can't understand how you would choose which rows get the change, and can't understand how to apply a simply background colour as "option"! (Reading the documentation on QStyleOptionViewItem is sending my down the rabbit-hole!).

Can you help?

Answer Source

We must obtain the data in the archive column (in my example it is the third one) and verify that it satisfies the condition (in this case true), if so we return the QBrush object with the desired color.

def data(self, item, role):
    if role == Qt.BackgroundRole:
        if QSqlQueryModel.data(self, self.index(item.row(), 3), Qt.DisplayRole):
            return QBrush(Qt.yellow)
    return QSqlQueryModel.data(self, item, role)

Also in my case use the database SQLITE where there is no boolean data but emulate with the data type int restricted to values 0 or 1, so use the following instruction where it returns True or False according to 1 or 0, respectively.

def data(self, item, role):
    [...]
    if role == Qt.DisplayRole:
        if item.column() == 3:
            return True if QSqlQueryModel.data(self, item, Qt.DisplayRole) == 1 else False
    return QSqlQueryModel.data(self, item, role)

In short use the following code, in addition the complete code is here:

def data(self, item, role):
    if role == Qt.BackgroundRole:
        if QSqlQueryModel.data(self, self.index(item.row(), 3), Qt.DisplayRole):
            return QBrush(Qt.yellow)
    if role == Qt.DisplayRole:
        if item.column() == 3:
            return True if QSqlQueryModel.data(self, item, Qt.DisplayRole) == 1 else False
    return QSqlQueryModel.data(self, item, role)

Screenshot:

enter image description here

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download