By default, the setData() method is called when the editor is closed since the commitData and closeEditor signal is emitted, that logic is implemented for certain default widgets but in the case of your custom widget no, so the solution is emit the commitData signal when the button is pressed.
On the other hand do not reinvent the wheel since QToolButton can be checkable since it inherits from QAbstractButton.
Considering the above, the solution is:
# ...
class ColorCheckBox(QtWidgets.QToolButton):
def __init__(self, parent=None):
super().__init__(parent)
self.setStyleSheet(
"""
ColorCheckBox{
border: 2px solid red;
background-color: red
}
ColorCheckBox:checked{
border: 2px solid green;
background-color: green
}
"""
)
self.setCheckable(True)
def set_data(self, value):
self.setChecked(validate(value, bool))
def data(self):
return self.isChecked()
# ...
class Delegate(QtWidgets.QStyledItemDelegate):
def createEditor(self, parent, option, index):
widget = ColorCheckBox(parent)
widget.toggled.connect(self._commit)
return widget
def setModelData(self, widget, model, index):
model.setData(index, widget.data())
def setEditorData(self, widget, index):
widget.set_data(index.data())
@QtCore.pyqtSlot()
def _commit(self):
widget = self.sender()
self.commitData.emit(widget)
class Model(QtCore.QAbstractTableModel):
# ...
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid() or role != QtCore.Qt.DisplayRole:
return QtCore.QVariant()
return QtCore.QVariant(False) # <---
# ...









