What is "role" and where it comes from? (How to change background color after editing QTableView cell?)
pyqt, python, qtableview
Solution
It's the part of QAbstractItemModel interface. See:
- http://qt-project.org/doc/qt-4.8/qabstractitemmodel.html#data
- http://qt-project.org/doc/qt-4.8/qt.html#ItemDataRole-enum
If you'd like to learn more about Qt Model/View(/Controller) approach, there is also a tutorial:
- http://qt-project.org/doc/qt-4.8/model-view-programming.html#item-roles
Edit (a little program explanation):
Well, obviously you created an implementation QAbstractTableModel which has a little bit more specialized interface than QAbstractItemModel. It's "abstract", so it means that you have to provide a working implementation. On the other hand it already implements some of QAbstractItemModel methods, like `createIndex()`. Your model implementation is used internally by Qt when accessing informations about your table.
The most important methods are `data()` for data access and `setData()` for changing the data. Your data is a two-dimensional array of pairs: `[string, bool]`. The first element is the text that you displayed in table cell and the second element is a property holding information whether that specific element has been changed.
Those methods are usually called by Qt, e.g. when you edit a cell, move your mouse over widget, etc. For example, if hold your mouse over a table cell for a few moments, Qt will call `data(cellIndex, QtCore.Qt.TooltipRole)` so you'll be able to display a tooltip text. So in this case `roles` reflect activities or actions that user has taken. Like docs say:
Each item in the model has a set of data elements associated with it, each with its own role. The roles are used by the view to indicate to the model which type of data it needs. Custom models should return data in these types.
You don't have to serve all data roles. You can simply return `QVariant()` in C++ or `None` in Python (Python doesn't really need something like `QVariant` because it's dynamically typed). Remember that when you reach end of function in Python and don't return anything, Python will return `None` by default.
There is also `flags()` method which tells Qt what actions user will be available to do. Remove `QtCore.Qt.ItemIsEditable` and you won't be able to edit your table. A little trick here is that those flags have int values that are powers of 2. This way they can be easily OR-ed (sorry if it's not the correct verb for bitwise OR ;)) and returned as a single integer.
So when you for example double click cell, Qt first checks `flags()`. If `QtCore.Qt.ItemIsEditable` is set, it changes that cell to text area in which you can type a new value. If you leave it (e.g. by pressing Enter or selecting a another cell), it will call `setData(cellIndex, typedString, Qt.EditRole)` on your model. Moreover, `setData()` emits a signal which informs a View when data has been changed and that it should refresh data that it is displaying.
This approach gives us a separation of data controller and data viewer. `Model` doesn't know how data is displayed by views that use it (there might be more than one and they will be synchronised all the time). It's called MVC - Model/View/Controller. Unfortunately, Qt naming for its MVC implementation is misleading, but about it you can read more e.g. here.
Well, this response became a little too long but I hope that it's at least a little help for you. Good luck! :)
Problem
im trying to change the background color of a qtable cell after editing it. i already watched the qustion "How to change background color after editing QTableView cell?", the problem i have is, in the example from the answer, i dont understand where "role" comes from. i mean, where is role declared and where role change its value? i only see where role is compared to "Qt.Core.xxx" ``` import sys from PyQt4 import QtGui, QtCore class Model(QtCore.QAbstractTableModel): def __init__(self, parent=None): super(Model, self).__init__(parent) # list of lists containing [data for cell, changed] 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 QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled |QtCore.Qt.ItemIsEditable def data(self, index, role): if index.isValid(): data, changed = self._data[index.row()][index.column()] if role in [QtCore.Qt.DisplayRole, QtCore.Qt.EditRole]: return data if role == QtCore.Qt.BackgroundRole and changed: return QtGui.QBrush(QtCore.Qt.darkBlue) def setData(self, index, value, role): if role == QtCore.Qt.EditRole: # set the new value with True `changed` status self._data[index.row()][index.column()] = [value.toString(), True] self.dataChanged.emit(index, index) return True return False if __name__ == '__main__': app = QtGui.QApplication(sys.argv) t = QtGui.QTableView() m = Model(t) t.setModel(m) t.show() sys.exit(app.exec_()) ``` i cant just add a comment in the other question, because i dont have 50 "repution-points", sry.