6

i have this QTableView with custom model and delegate, how do i change the background color of the cell after editing it?

shall i do this in delegate's setModelData() ?

index.model.setData(index, QVariant(True),Qt.UserRole) 

and later in model's data() # it's calling itself ?

if role == Qt.BackgroundColorRole:
    if index.model().data(index,Qt.UserRole).toBool():
        return QVariant(QColor(Qt.darkBlue))

and in model's setData() i don't have any code like:

if role==Qt.UserRole:
    ....

what is the correct way of doing this ?

edit: Here is my whole setData() method in custom model

def setData(self, index, value, role=Qt.EditRole):

if index.isValid() and 0 <= index.row() < len(self.particles):
    particle = self.particles[index.row()]
    column = index.column()
    if column == ID:
        value,ok= value.toInt()
        if ok:
            particle.id =value                 
    elif column == CYCLEIDANDNAME:
        cycleId,cycleName= value.toString().split(' ')
        particle.cycleId =cycleId
#                also need to set cycleName
        for name in self.cycleNames:
            if name.endsWith(cycleName):
                particle.cycleFrameNormalized=particle.cycleName = name
                break

    elif column == CYCLEFRAME:
        value,ok= value.toInt()
        if ok:
            print 'set new val to :',value
            particle.cycleFrame =value 
#                    self.setData(index,QVariant(QColor(Qt.red)),Qt.BackgroundRole)

    elif column == CLASSID:
        value,ok= value.toInt()
        if ok:
            particle.classId =value                 
    elif column == VARIATIONID:
        value,ok= value.toInt()
        if ok:
            particle.variationId =value                 

    self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
              index, index)

    return True

return False

sorry still has no clue, i'll paste full code from rapid gui developement book example: i posted my code here http://pastebin.com/ShgRRMcY

how do i change to code to make cell background color change after edting the cell ?

Shuman
  • 3,914
  • 8
  • 42
  • 65
  • which model are you using? –  Dec 18 '12 at 10:30
  • @X.Jacobs I'm using a custom model inherited from `QAbstractTableModel`, and i have implemented my own `setData()` but it only deals with `Qt.EditRole` – Shuman Dec 19 '12 at 04:03
  • *how* does it deal with `Qt.EditRole`? please post a manageable version of your code –  Dec 19 '12 at 05:14
  • @Shuman: Calling `setData` in `setData` is kind of pointless. It'll call itself. You need to store that color somewhere in your data (`particle`?) where you can check in `data` method and return for `BackgroundRole`. And by the way, you're not using `role` in any way in the `setData`. – Avaris Dec 19 '12 at 07:53

2 Answers2

7

You need to keep track of the edited items in the model somehow. You don't need UserRole. You can keep this internally, but of course, if you want to expose this information to the outside UserRole is perfect for this.

Here is a simple example. You can adjust this to your code:

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_())
Avaris
  • 35,883
  • 7
  • 81
  • 72
  • thanks, i tried this although i'm using tableView. i used `self.setData(index,QVariant(QColor(Qt.red)),Qt.BackgroundRole)` in my `setData()` in my model, but it doesn't work. – Shuman Dec 19 '12 at 04:06
  • @Shuman: `setData` doesn't do anything by itself. You should be storing the data passed to it. It might be better if you showed your model. – Avaris Dec 19 '12 at 04:53
  • @Shuman try again and see what happens when you `self.setData(index,"foo-bar",Qt.EditRole)` –  Dec 19 '12 at 05:11
  • @Avaris @X.Jacobs i've pasted my model to pastebin, can i just store the userRole data in the cell itself ? i mean if i use default table model, it'll store it, but now i'm using a custom model with customized `setData()` how could i save the value in the cell itself? (or actually, even the default model is not saving the value in the cell itself, it stores the value in some instance variable on the model ). – Shuman Dec 20 '12 at 01:26
-2

QTableWidget has a signal itemChanged that needs to be connected to a slot. Once connected to a slot the signal will pass in the QTableWidgetItem that has been changed. From there you can use the methods for QTableWidgetItem such as setBackgroundColor to change the background.

Here's an example

#! /usr/bin/env python2.7

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


class Main(QTableWidget):

    def __init__(self):

        super(Main, self).__init__(2, 5)
        layout = QHBoxLayout(self)

        self.itemChanged.connect(self.changeBG)

    def changeBG(self, cell):

        cell.setBackgroundColor(QColor(225, 0, 225))

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = Main()
    main.show()
    app.exec_()
Jeff
  • 6,932
  • 7
  • 42
  • 72