PyQt Tableview row background colour based on cell

2019-02-15 19:27发布

问题:

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?

回答1:

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: