I create a class 'pandasModel' based on QAbstractTableModel, shown below:
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)
Also I create a QTableView to show the Model, shown below:
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_())
We can show data in QTableview now, but question is how can i call function 'set_cell_color' to set the background color for cell with given row and column, so could you please tell me how to finish the code in def set_cell_color?
once i want to set cell's color by using 'model.item(row, col).setBackground(QColor(240, 255, 240))' just like QStandardItemModel, but raise error ''model' has no attribute 'item''
this link shows a method to set cell's color
code shows below:
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_())
Use 'return QBrush(Qt.red)' in 'data' function upon can set the background-color of cells with value 'In error', but the background-color was already set when the Qtableview finish created, i just want to set cell's background color when i call function 'set_cell_color' ,that means i can control the cell's background even after Qtableview already been created, i will really appreciate for your help.
The logic is to save the information in the model associating the item's position and the item's color, and to update it, the dataChanged signal must be emitted.
Note:Your model is of type table so you must inherit from QAbstractTableModel and not from QAbstractItemModel
Considering the above, the solution is:
class pandasModel(QAbstractTableModel):
    def __init__(self, data, parent=None):
        QAbstractItemModel.__init__(self, parent)
        self._data = data
        self.colors = dict()
    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()])
            if role == Qt.BackgroundRole:
                color = self.colors.get((index.row(), index.column()))
                if color is not None:
                    return color
        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)
    def change_color(self, row, column, color):
        ix = self.index(row, column)
        self.colors[(row, column)] = color
        self.dataChanged.emit(ix, ix, (Qt.BackgroundRole,))
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]])
        self.model = pandasModel(data)
        self.table.setModel(self.model)
    def set_cell_color(self, row, column):
        self.model.change_color(row, column, QBrush(Qt.red))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With