如何控制QTableView Items的背景颜色

How to control QTableView Items Background color

源模型的 data() 将 QTableView 的每个索引背景颜色设置为绿色(如果索引的行号为偶数)和蓝色(如果为奇数)。

然后代理模型过滤掉每隔三个索引。所以结果颜色都是无序的。

问题是背景颜色是在代理模型过滤索引之前在源模型中分配的。

这里是源代码:

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

class MyTableModel(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.items = [i for i in range(90)]

    def rowCount(self, parent):
        return len(self.items)       
    def columnCount(self, parent):
        return 1

    def data(self, index, role):
        if not index.isValid():
            return QVariant()

        row=index.row()
        column=index.column()

        if role == Qt.DisplayRole:
            if row<len(self.items):
                return QVariant(self.items[row])
            else:
                return QVariant()

        if role==Qt.BackgroundColorRole:
            if row%2: bgColor=QColor(Qt.green)
            else: bgColor=QColor(Qt.blue)        
            return QVariant(QColor(bgColor))


class Proxy01(QSortFilterProxyModel):
    def __init__(self):
        super(Proxy01, self).__init__()

    def filterAcceptsRow(self, row, parent):
        if row%3: return True
        else: return False

class MyWindow(QWidget):
    def __init__(self, *args):
        QWidget.__init__(self, *args)

        self.tablemodel=MyTableModel(self)               

        self.proxy1=Proxy01()
        self.proxy1.setSourceModel(self.tablemodel)

        tableviewA=QTableView(self) 
        tableviewA.setModel(self.proxy1)
        tableviewA.setSortingEnabled(True) 
        tableviewA.horizontalHeader().setSortIndicator(0, Qt.AscendingOrder)
        tableviewA.horizontalHeader().setStretchLastSection(True)

        layout = QVBoxLayout(self)
        layout.addWidget(tableviewA)

        self.setLayout(layout)

    def test(self, arg):
        print arg

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_()) 

不要依赖源模型的 data()if Qt.BackgroundColorRole: 方法的功能,而是将 tableviewA.setAlternatingRowColors(True) 设置为 True。它与 CSS 配合得很好。下面发布了一个完全有效的解决方案(请注意 Qt.BackgroundColorRole 已被注释掉。否则它将优先于 CSS):

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

class MyTableModel(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.items = [i for i in range(90)]

    def rowCount(self, parent):
        return len(self.items)       
    def columnCount(self, parent):
        return 1

    def data(self, index, role):
        if not index.isValid():
            return QVariant()

        row=index.row()
        column=index.column()

        if role == Qt.DisplayRole:
            if row<len(self.items):
                return QVariant(self.items[row])
            else:
                return QVariant()

        # if role==Qt.BackgroundColorRole:
        #     if row%2: bgColor=QColor(Qt.green)
        #     else: bgColor=QColor(Qt.blue)        
        #     return QVariant(QColor(bgColor))


class Proxy01(QSortFilterProxyModel):
    def __init__(self):
        super(Proxy01, self).__init__()

    def filterAcceptsRow(self, row, parent):
        if row%3: return True
        else: return False

class MyWindow(QWidget):
    def __init__(self, *args):
        QWidget.__init__(self, *args)

        self.tablemodel=MyTableModel(self)               

        self.proxy1=Proxy01()
        self.proxy1.setSourceModel(self.tablemodel)

        tableviewA=QTableView(self) 
        tableviewA.setModel(self.proxy1)
        tableviewA.setSortingEnabled(True) 
        tableviewA.horizontalHeader().setSortIndicator(0, Qt.AscendingOrder)
        tableviewA.horizontalHeader().setStretchLastSection(True)
        tableviewA.setAlternatingRowColors(True)
        tableviewA.setStyleSheet("alternate-background-color: yellow; background-color: red;");

        layout = QVBoxLayout(self)
        layout.addWidget(tableviewA)

        self.setLayout(layout)

    def test(self, arg):
        print arg

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())