Python 如何在使用自定义QAbstractTableModel创建Qtableview后为单元格着色

Python 如何在使用自定义QAbstractTableModel创建Qtableview后为单元格着色,python,pyqt,qtableview,qabstracttablemodel,Python,Pyqt,Qtableview,Qabstracttablemodel,我基于QabStretctTableModel创建了一个类“PandaModel”,如下所示: import sys from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PyQt5.QtCore import * class pandasModel(QAbstractItemModel): def __init__(self, data, parent=None): QAbstractI

我基于QabStretctTableModel创建了一个类“PandaModel”,如下所示:

import sys
from PyQt5.QtGui     import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore    import *
class pandasModel(QAbstractItemModel):

    def __init__(self, data, parent=None):
        QAbstractItemModel.__init__(self, parent)
        self._data = data

    def rowCount(self, parent=None):
        return self._data.index.size

    def columnCount(self, parent=None):
        return self._data.columns.size

    def data(self, index, role=Qt.DisplayRole):
        if index.isValid():
            if role == Qt.DisplayRole:
                return str(self._data.iloc[index.row(), index.column()])
            if role == Qt.EditRole:
                return str(self._data.iloc[index.row(), index.column()])
        return None

    def headerData(self, rowcol, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self._data.columns[rowcol]
        if orientation == Qt.Vertical and role == Qt.DisplayRole:
            return self._data.index[rowcol]
        return None

    def flags(self, index):
        flags = super(self.__class__, self).flags(index)
        flags |= Qt.ItemIsEditable
        flags |= Qt.ItemIsSelectable
        flags |= Qt.ItemIsEnabled
        flags |= Qt.ItemIsDragEnabled
        flags |= Qt.ItemIsDropEnabled
        return flags

    def sort(self, Ncol, order):
        """Sort table by given column number.
        """
        try:
            self.layoutAboutToBeChanged.emit()
            self._data = self._data.sort_values(self._data.columns[Ncol], ascending=not order)
            self.layoutChanged.emit()
        except Exception as e:
            print(e)
class TableWin(QWidget):
    pos_updown = -1
    pos_save = []

    def __init__(self):
        super(TableWin, self).__init__()
        self.resize(200, 100)
        self.table = QTableView(self)
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.table)
        self.setLayout(self.v_layout)
        self.showdata()

    def showdata(self):
        data = pd.DataFrame([[1,2,3,4],[5,6,7,8]])
        model = pandasModel(data)
        self.table.setModel(model)

    def set_cell_color(self, row, column)
        '''
          Pass two arguments to this function, which is called to set
          the background color of the cell corresponding to the row and column
        '''
if __name__ == '__main__':
    app = QApplication(sys.argv)
    tableView = TableWin()
    # I want to change cell's color by call function 'set_cell_color' here
    # tableView.set_cell_color(row=1,column=1) 
    tableView.show()
    sys.exit(app.exec_())
我还创建了一个QTableView来显示模型,如下所示:

import sys
from PyQt5.QtGui     import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore    import *
class pandasModel(QAbstractItemModel):

    def __init__(self, data, parent=None):
        QAbstractItemModel.__init__(self, parent)
        self._data = data

    def rowCount(self, parent=None):
        return self._data.index.size

    def columnCount(self, parent=None):
        return self._data.columns.size

    def data(self, index, role=Qt.DisplayRole):
        if index.isValid():
            if role == Qt.DisplayRole:
                return str(self._data.iloc[index.row(), index.column()])
            if role == Qt.EditRole:
                return str(self._data.iloc[index.row(), index.column()])
        return None

    def headerData(self, rowcol, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self._data.columns[rowcol]
        if orientation == Qt.Vertical and role == Qt.DisplayRole:
            return self._data.index[rowcol]
        return None

    def flags(self, index):
        flags = super(self.__class__, self).flags(index)
        flags |= Qt.ItemIsEditable
        flags |= Qt.ItemIsSelectable
        flags |= Qt.ItemIsEnabled
        flags |= Qt.ItemIsDragEnabled
        flags |= Qt.ItemIsDropEnabled
        return flags

    def sort(self, Ncol, order):
        """Sort table by given column number.
        """
        try:
            self.layoutAboutToBeChanged.emit()
            self._data = self._data.sort_values(self._data.columns[Ncol], ascending=not order)
            self.layoutChanged.emit()
        except Exception as e:
            print(e)
class TableWin(QWidget):
    pos_updown = -1
    pos_save = []

    def __init__(self):
        super(TableWin, self).__init__()
        self.resize(200, 100)
        self.table = QTableView(self)
        self.v_layout = QVBoxLayout()
        self.v_layout.addWidget(self.table)
        self.setLayout(self.v_layout)
        self.showdata()

    def showdata(self):
        data = pd.DataFrame([[1,2,3,4],[5,6,7,8]])
        model = pandasModel(data)
        self.table.setModel(model)

    def set_cell_color(self, row, column)
        '''
          Pass two arguments to this function, which is called to set
          the background color of the cell corresponding to the row and column
        '''
if __name__ == '__main__':
    app = QApplication(sys.argv)
    tableView = TableWin()
    # I want to change cell's color by call function 'set_cell_color' here
    # tableView.set_cell_color(row=1,column=1) 
    tableView.show()
    sys.exit(app.exec_())
我们现在可以在QTableview中显示数据,但问题是我如何调用函数“set_cell_color”来设置给定行和列的单元格的背景色,所以您能告诉我如何在def set_cell_color中完成代码吗

一旦我想使用“model.item(row,col).setBackground(QColor(240255,240))”设置单元格的颜色,就像QStandardItemModel一样,但引发错误“model”没有属性“item”

代码如下:

import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *


class Model(QAbstractTableModel):
    def __init__(self, parent=None):
        super(Model, self).__init__(parent)
        self._data = [[['%d - %d' % (i, j), False] for j in range(10)] for i in range(10)]

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

    def columnCount(self, parent):
        return len(self._data[0])

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

    def data(self, index, role):
        if index.isValid():
            data, changed = self._data[index.row()][index.column()]

        if role in [Qt.DisplayRole, Qt.EditRole]:
            return data

        if role == Qt.BackgroundRole and data == "In error":        # <---------
            return QBrush(Qt.red) 

    def setData(self, index, value, role):
        if role == Qt.EditRole:
            self._data[index.row()][index.column()] = [value, True]
            self.dataChanged.emit(index, index)
            return True
        return False

if __name__ == '__main__':
    app = QApplication(sys.argv)
    tableView = QTableView()
    m = Model(tableView)
    tableView.setModel(m)
    tableView.show()
    sys.exit(app.exec_())
导入系统 从PyQt5.QtGui导入* 从PyQt5.QtWidgets导入* 从PyQt5.QtCore导入* 类模型(QAbstractTableModel): def uuu init uuu(self,parent=None): 超级(模型,自我).\uuuu初始\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu self.\u data=[[['%d-%d'(i,j),对于范围(10)中的j为False]i对于范围(10)] def行数(自身、父级): 返回长度(自身数据) def列数(自身、父项): 返回长度(自身数据[0]) def标志(自、索引): 返回Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable def数据(自身、索引、角色): 如果index.isValid(): 数据,已更改=self.\u数据[index.row()][index.column()] 如果[Qt.DisplayRole,Qt.EditRole]中的角色: 返回数据
如果role==Qt.BackgroundRole and data==“In error”:#逻辑是将项目位置和项目颜色关联的信息保存在模型中,并进行更新,必须发出dataChanged信号

注意:您的模型属于table类型,因此您必须从QAbstractTableModel继承,而不是从QAbstractItemModel继承

考虑到上述情况,解决方案是:

类pandasModel(QAbstractTableModel): def uuu init uuu(self,data,parent=None): QAbstractItemModel.\uuuuu init\uuuuuuu(自,父) self.\u data=数据 self.colors=dict() def行数(自身,父项=无): 返回self.\u data.index.size def columnCount(自身,父项=无): 返回self.\u data.columns.size def数据(self,index,role=Qt.DisplayRole): 如果index.isValid(): 如果角色==Qt.DisplayRole: 返回str(self.\u data.iloc[index.row(),index.column()) 如果角色==Qt.EditRole: 返回str(self.\u data.iloc[index.row(),index.column()) 如果角色==Qt.BackgroundRole: color=self.colors.get((index.row(),index.column()) 如果颜色不是无: 返回颜色 一无所获 def headerData(自身、行列、方向、角色): 如果方向==Qt.Horizontal且角色==Qt.DisplayRole: 返回self.\u数据列[rowcol] 如果方向==Qt.Vertical且角色==Qt.DisplayRole: 返回self.\u数据索引[rowcol] 一无所获 def标志(自、索引): flags=super(self.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu 标志|=Qt.ItemIsEditable 标志|=Qt.itemselectable 标志|=Qt.ItemIsEnabled 标志|=Qt.ItemIsDragEnabled 标志|=Qt.itemsropertable 返回标志 def排序(自身、Ncol、顺序): “”“按给定的列号对表进行排序。 """ 尝试: self.layoutaboutbechanged.emit() self.\u data=self.\u data.sort\u值( self.\u data.columns[Ncol],升序=非顺序 ) self.layoutChanged.emit() 例外情况除外,如e: 打印(e) def更改颜色(自身、行、列、颜色): ix=自索引(行、列) self.colors[(行、列)]=颜色 self.dataChanged.emit(ix,ix,(Qt.BackgroundRole,) 类TableWin(QWidget): 位置向上向下=-1 pos_save=[] 定义初始化(自): 超级(TableWin,self)。\uuuu init\uuuuu() 自我调整大小(200100) self.table=QTableView(self) self.v_layout=QVBoxLayout() self.v_layout.addWidget(self.table) self.setLayout(self.v_布局) self.showdata() def showdata(自): data=pd.DataFrame([[1,2,3,4],[5,6,7,8]] self.model=pandasModel(数据) self.table.setModel(self.model) def设置单元格颜色(自身、行、列): self.model.change_颜色(行、列、QBrush(Qt.red))
非常感谢,你解决了我的问题,真是太好了perfectly@xufang如果这个答案对您有帮助,请不要忘记标记为正确,如果您不知道如何做,请检查