python - QTreeView 请求无效行的索引
问题描述
看看下面的 MWE。
它很简单QAbstractItemModel
,只有一个级别,将其项目存储在列表中。我创建了一个QTreeView
来显示模型,以及一个按钮来删除第二个项目。
from PyQt5.QtCore import QModelIndex, QAbstractItemModel, Qt
from PyQt5.QtWidgets import QTreeView, QApplication, QPushButton
class Item:
def __init__(self, title):
self.title = title
class TreeModel(QAbstractItemModel):
def __init__(self, parent=None):
super().__init__(parent)
self._items = [] # typing.List[Item]
def addItem(self, item: Item):
self.beginInsertRows(QModelIndex(), len(self._items), len(self._items))
self._items.append(item)
self.endInsertRows()
def removeItem(self, item: Item):
index = self._items.index(item)
self.beginRemoveRows(QModelIndex(), index, index)
self._items.remove(item)
self.endRemoveRows()
# ----- overridden methods from QAbstractItemModel -----
# noinspection PyMethodOverriding
def data(self, index: QModelIndex, role):
item = index.internalPointer()
if role == Qt.DisplayRole:
return item.title
# noinspection PyMethodOverriding
def rowCount(self, parent=QModelIndex()):
if not parent.isValid():
return len(self._items)
return 0
# noinspection PyMethodOverriding
def columnCount(self, parent=QModelIndex()):
return 1
# noinspection PyMethodOverriding
def index(self, row: int, col: int, parent=QModelIndex()):
assert not parent.isValid()
return self.createIndex(row, 0, self._items[row])
def parent(self, index=QModelIndex()):
return QModelIndex()
def removeItem():
model.removeItem(item2)
if __name__ == '__main__':
app = QApplication([])
model = TreeModel()
button = QPushButton('Delete')
button.clicked.connect(removeItem)
button.show()
item1 = Item('Item 1')
model.addItem(item1)
item2 = Item('Item 2')
model.addItem(item2)
treeView = QTreeView()
treeView.setModel(model)
treeView.show()
app.exec()
据我所知,我的模型的实现是正确的(虽然非常基本)。特别是,它报告的行数和列数是正确的,并且它永远不会为无效的数据创建索引。
重现我的问题的步骤:
- 运行上面的代码。
- 在树视图中,选择项目 2。
- 按删除按钮。
在我的系统上,应用程序在 中崩溃beginRemoveRows()
,因为视图请求QModelIndex
第 2 行的 a。自然,第 2 行不存在。
知道为什么QTreeView
当模型明确报告只有 2 行时会认为会有 3 行吗?
解决方案
当添加、移动、删除等项目时,模型所做的是验证 QPersistentModelIndex 是否有效,因此它会调用 QAbstractItemModel 的index()方法。在该方法中,开发人员有责任验证行或列是否有效,并且模型提供了您不使用的hasIndex()方法导致您指出的错误,因此解决方案是:
def index(self, row: int, col: int, parent=QModelIndex()):
if not self.hasIndex(row, col, parent):
return QModelIndex()
assert not parent.isValid()
return self.createIndex(row, 0, self._items[row])
推荐阅读
- aem - 在 AEM 中停止版本清除
- mongodb - MongoDB 触发器 - 匹配表达式
- angular - 为帖子编写业力测试用例并以 Angular 8 获得服务
- wpf - 更改 telerik:RadTimeBar 间隔标签颜色
- css - 是什么导致 padding:10px 在顶部显得更大?
- xml - Notepad++:2 行搜索,如果缺失则插入 1
- react-redux - 从状态数组中删除项目中的状态含义 - useReducer
- http - 在 Flutter 中使用 Dio 时忽略响应头
- sql - 蜂巢查询 | 在 DML 中使用 group by
- ssms-2014 - SQL Server Management Studio 无法再连接到远程服务器