I'm implementing a delegate for a QTableView where two columns should be dropdowns where the user selects a value from an enum.
Below is an example:
from PyQt4 import QtGui, QtCore
import enum
Color = enum.Enum("Color", ("RED", "BLUE"))
Shape = enum.Enum("Shape", ("TRIANGLE", "CIRCLE"))
class EnumComboBoxDelegate(QtGui.QItemDelegate):
def __init__(self, enum_cls, parent=None):
super(EnumComboBoxDelegate, self).__init__(parent)
self.enum_cls = enum_cls
self.enum_objects = list(enum_cls)
self.enum_names = [enum_obj.name for enum_obj in self.enum_objects]
self.enum_values = [enum_obj.value for enum_obj in self.enum_objects]
def createEditor(self, widget, option, index):
editor = QtGui.QComboBox(widget)
for user_friendly_name in self.enum_names:
editor.addItem(user_friendly_name)
return editor
def setEditorData(self, editor, index):
combobox_index, is_int = index.model().data(index, QtCore.Qt.EditRole).toInt()
if is_int:
editor.setCurrentIndex(combobox_index)
else:
editor.setCurrentIndex(0)
def setModelData(self, editor, model, index):
combobox_index = editor.currentIndex()
if not combobox_index:
combobox_index = 0
model.setData(index, combobox_index, QtCore.Qt.EditRole)
def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
class CentralWidget(QtGui.QWidget):
def __init__(self, *args, **kwargs):
super(CentralWidget, self).__init__(*args, **kwargs)
main_layout = QtGui.QVBoxLayout()
table_view = QtGui.QTableView()
table_view.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
table_view.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
table_model = QtGui.QStandardItemModel(2, 2, None)
table_view.setModel(table_model)
color_combo_delegate = EnumComboBoxDelegate(Color)
table_view.setItemDelegateForColumn(0, color_combo_delegate)
shape_combo_delegate = EnumComboBoxDelegate(Shape)
table_view.setItemDelegateForColumn(1, shape_combo_delegate)
main_layout.addWidget(table_view)
self.setLayout(main_layout)
def run_self_contained_widget():
import sys
app = QtGui.QApplication(sys.argv)
main_window = QtGui.QMainWindow()
main_window.setCentralWidget(CentralWidget())
main_window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
run_self_contained_widget()
Now, if run, the code crashes on startup without traceback:
Process finished with exit code -1073741819 (0xC0000005)
If I change the delegates so they both use the same instance of EnumComboBoxDelegate
, I get no errors:
color_combo_delegate = EnumComboBoxDelegate(Color)
table_view.setItemDelegateForColumn(0, color_combo_delegate)
shape_combo_delegate = EnumComboBoxDelegate(Shape)
table_view.setItemDelegateForColumn(1, color_combo_delegate)
What is causing this and how do I fix it? This code is using PyQt4 and Python 2.7, but it seems to be the same in Python 3.x