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))