QStandardItemModel doesn't update QTableView
-
class EventsTableModel(QStandardItemModel): EVENT = 1000 def __init__(self, et: EventTree, show_only: list[EventEnum]) -> None: super().__init__(None) self.et = et self.events = tuple(et.get(*show_only)) self.set_horizontal_header_labels(["ID", "Value"]) for event in self.events: id_item = QStandardItem(str(event.id)) id_item.set_editable(False) val_item = QStandardItem() val_item.set_data(event, self.EVENT) try: val_item.set_data(event.value, Qt.ItemDataRole.DisplayRole) except NotImplementedError: continue self.append_row((id_item, val_item)) def set_data(self, index: QModelIndex, value, role: int = ...) -> bool: event = index.data(self.EVENT) try: event.value = value except Exception as exc: logging.exception(exc) return False else: self.dataChanged.emit(index, index) # type: ignore return TrueWhen I try to enter a new value in a cell's editor and press Enter, the new value doesn't appear in the cell. This occurs even if there are no exceptions.
I am using a normal QTableView instance for this model. The data gets correctly displayed initially after loading.
PySide: 6.4.2
EDIT: Fixed it by adding this line before emitting
dataChanged:self.item_from_index(index).set_data(value, Qt.ItemDataRole.DisplayRole) -
D demberto has marked this topic as solved on
-
class EventsTableModel(QStandardItemModel): EVENT = 1000 def __init__(self, et: EventTree, show_only: list[EventEnum]) -> None: super().__init__(None) self.et = et self.events = tuple(et.get(*show_only)) self.set_horizontal_header_labels(["ID", "Value"]) for event in self.events: id_item = QStandardItem(str(event.id)) id_item.set_editable(False) val_item = QStandardItem() val_item.set_data(event, self.EVENT) try: val_item.set_data(event.value, Qt.ItemDataRole.DisplayRole) except NotImplementedError: continue self.append_row((id_item, val_item)) def set_data(self, index: QModelIndex, value, role: int = ...) -> bool: event = index.data(self.EVENT) try: event.value = value except Exception as exc: logging.exception(exc) return False else: self.dataChanged.emit(index, index) # type: ignore return TrueWhen I try to enter a new value in a cell's editor and press Enter, the new value doesn't appear in the cell. This occurs even if there are no exceptions.
I am using a normal QTableView instance for this model. The data gets correctly displayed initially after loading.
PySide: 6.4.2
EDIT: Fixed it by adding this line before emitting
dataChanged:self.item_from_index(index).set_data(value, Qt.ItemDataRole.DisplayRole) -
@demberto
Yourset_data()method does not use theroleparameter passed to it, which it should, or you should not have it accept such a parameter.
If you do make it use the parameter, you should be passingQt.ItemDataRole.EditRolenotDisplayRole.@JonB Do you mean the place where I call
self.item_from_index(index).set_data(value, Qt.ItemDataRole.DisplayRole)?OR do you mean this?
def set_data(self, index: QModelIndex, value, role: int = ...) -> bool: event = index.data(self.EVENT) try: event.value = value except Exception as exc: logging.exception(exc) return False else: self.item_from_index(index).set_data(value, role) self.dataChanged.emit(index, index) # type: ignore return TrueEDIT: That works
I still don't understand why I have to callself.item_from_index(index).set_data(value, role)explicitly. Isn't that whatset_datamechanism is supposed to do internally, or I should call super-classset_datain myelseclause? -
@JonB Do you mean the place where I call
self.item_from_index(index).set_data(value, Qt.ItemDataRole.DisplayRole)?OR do you mean this?
def set_data(self, index: QModelIndex, value, role: int = ...) -> bool: event = index.data(self.EVENT) try: event.value = value except Exception as exc: logging.exception(exc) return False else: self.item_from_index(index).set_data(value, role) self.dataChanged.emit(index, index) # type: ignore return TrueEDIT: That works
I still don't understand why I have to callself.item_from_index(index).set_data(value, role)explicitly. Isn't that whatset_datamechanism is supposed to do internally, or I should call super-classset_datain myelseclause?@demberto
Yes, you should call baseQStandardItemModel.setData()to handle the case you don't.Your code is bad for the normal, successful case. You do not return
True, you just drop off the end of the method and Python will doubtless returnNone/False, could be a problem.The base
setData()defaultsrole = EditRolefor the parameter. You really ought do so too.Where you call it you show
self.item_from_index(index).set_data(value, Qt.ItemDataRole.DisplayRole). That should really beEditRole, or you can omit it if you change to default as per previous point. -
@demberto
Yes, you should call baseQStandardItemModel.setData()to handle the case you don't.Your code is bad for the normal, successful case. You do not return
True, you just drop off the end of the method and Python will doubtless returnNone/False, could be a problem.The base
setData()defaultsrole = EditRolefor the parameter. You really ought do so too.Where you call it you show
self.item_from_index(index).set_data(value, Qt.ItemDataRole.DisplayRole). That should really beEditRole, or you can omit it if you change to default as per previous point.@JonB Finally:
Your code is bad for the normal, successful case. You do not return True, you just drop off the end of the method and Python will doubtless return None/False, could be a problem.
def set_data(self, index: QModelIndex, value, role: int = Qt.ItemDataRole.EditRole) -> bool: event = index.data(self.EVENT) try: event.value = value except Exception as exc: logging.exception(exc) return False else: super().set_data(index, value, role) return TrueThanks!
-
@JonB Finally:
Your code is bad for the normal, successful case. You do not return True, you just drop off the end of the method and Python will doubtless return None/False, could be a problem.
def set_data(self, index: QModelIndex, value, role: int = Qt.ItemDataRole.EditRole) -> bool: event = index.data(self.EVENT) try: event.value = value except Exception as exc: logging.exception(exc) return False else: super().set_data(index, value, role) return TrueThanks!