我有一个2列的treeView,简单的继承深度为2;根>父>子。我在treeView子类中有一个removeRows调用,当按下delete键时,它会被求值。当我删除除最后一行以外的任何一行时,这似乎都很有效。
我收到一个IndexError: list index out of range
,它似乎来自节点类child
方法。当在模型的removeRows
中调用self.beginRemoveRows
方法时,似乎会发生这种情况。奇怪的是,操作的顺序似乎颠倒了,或者线程在模型知道它最近的更新之前就以某种方式导致了刷新。
有了这些代码片段,我希望有人能提供一个可能的解释或一些想法,说明下一步该如何调试。
来自QTreeView子类,
def keyPressEvent(self, event):
if event.key() == Qt.Key_Delete:
index = self.currentIndex()
self.model().removeRow(index.row())
else:
# call base class keyPressEvent
QTreeView.keyPressEvent(self, event)
来自QAbstractItemModel子类,
def index(self, row, column, parent=QModelIndex()):
parent_node = self.getNode(parent)
child_item = parent_node.child(row)
if child_item:
return self.createIndex(row, column, child_item)
else:
return QModelIndex()
def getNode(self, index):
if index.isValid():
node = index.internalPointer()
if node:
return node
return self._root
def removeRows(self, position, rows, parent=QModelIndex()):
parent_node = self.getNode(parent)
self.beginRemoveRows(parent, position, position + rows - 1)
parent_node.removeChild(position)
self.endRemoveRows()
return True
从节点类,
def child(self, row):
return self._children[row]
def removeChild(self, position):
if position < 0 or position >= len(self._children):
return False
child = self._children.pop(position)
child._parent = None
return True
我花了一些时间,但我终于找到了错误的原因:根据index
方法中的这封邮件,在继续之前,您应该检查索引是否存在。令人烦恼的是,它没有写在方法描述中,也没有写在qt4或qt5文档中。
index
方法的正确实现应该是在线的:
def index(self, row, column, parent=QModelIndex()):
if self.hasIndex(row, column, parentIndex):
parent_node = self.getNode(parent)
child_item = parent_node.child(row)
if child_item:
return self.createIndex(row, column, child_item)
else:
return QModelIndex()
在我的应用程序中,这解决了问题。
对QTreeView的更改似乎起到了作用。不过,我并不完全肯定这个问题不是由其他原因引起的。
def keyPressEvent(self, event):
if event.key() == Qt.Key_Delete:
index = self.currentIndex()
if not index.isValid(): return
parent = index.parent()
# adjust selection so refresh does not trigger IndexError
self.selectionModel().setCurrentIndex(self.indexAbove(index), QItemSelectionModel.ClearAndSelect)
# remove selected
self.model().removeRow(row, parent=parent)
return
# call base class keyPressEvent
QTreeView.keyPressEvent(self, event)