Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
6.8.1
-
None
Description
When a simple QTableView is used to display the data of a QAbstractTableModel and a row is selected and removed, the following QTableView.selectionChanged signal is emitted twice and second time the `selected: QItemSelection` arguments provides empty selection, even if actually the next row is correctly selected.
With the mwe at the bottom, it's easy to reproduce this behavior. Simply select a row, e.g. row with index 2, then delete it using the Delete key.
You'll see an output similar like below, note the second "selectionChanged ...", which shouldn't happen.
CustomTableModel.removeRow(row=2) selectionChanged: indexes=[<PySide6.QtCore.QModelIndex(3,0,0x0,...>] actual_indexes=[<PySide6.QtCore.QModelIndex(3,0,0x0,...>] selectionChanged: indexes=[] actual_indexes=[<PySide6.QtCore.QModelIndex(3,0,0x0,...>]
MWE
import PySide6 from PySide6 import QtGui, QtCore, QtWidgets print(PySide6.__version__) # Reproducible with 6.8.1 class CustomTableModel(QtCore.QAbstractTableModel): def __init__(self): super().__init__() self._data = [i for i in range(0,10)] def rowCount(self, parent=QtCore.QModelIndex()): return len(self._data) def columnCount(self, parent=QtCore.QModelIndex()): return 1 def data(self, index, role=QtCore.Qt.DisplayRole): column = index.column() row = index.row() if role == QtCore.Qt.DisplayRole: if column == 0 and row <= self.rowCount(): return str(self._data[row]) return None def removeRow(self, row: int, parent: QtCore.QModelIndex | None = None) -> bool: print(f"CustomTableModel.removeRow({row=})") if self.rowCount() <= 0: return False self.beginRemoveRows(QtCore.QModelIndex(), row, row) self._data.pop(row) self.endRemoveRows() return True class CustomTableView(QtWidgets.QTableView): def keyPressEvent(self, event: QtGui.QKeyEvent) -> None: if event.matches(QtGui.QKeySequence.StandardKey.Delete): selected_row = self.selectionModel().selectedRows()[0].row() if self.selectionModel().selectedRows() else -1 self.model().removeRow(selected_row) super().keyPressEvent(event) def selectionChanged(self, selected: QtCore.QItemSelection, deselected: QtCore.QItemSelection) -> None: super().selectionChanged(selected, deselected) indexes = selected.indexes() actual_indexes = self.selectionModel().selection().indexes() print(f"selectionChanged: {indexes=} {actual_indexes=}") class Widget(QtWidgets.QWidget): def __init__(self): super().__init__() # Getting the Model self.model = CustomTableModel() self.table_view = CustomTableView() self.table_view.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows) self.table_view.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.SingleSelection) self.table_view.setModel(self.model) self.main_layout = QtWidgets.QHBoxLayout() self.main_layout.addWidget(self.table_view) self.setLayout(self.main_layout) if __name__ == "__main__": app = QtWidgets.QApplication() widget = Widget() widget.show() app.exec()