我有一个2列树视图,简单的层次深度为2; root>父母>儿童。我在我的treeView子类中有一个removeRows调用,在按下删除键时会对其进行评估。当我删除任何行但最后一行时,这似乎工作正常。
我收到一个IndexError: list index out of range
,它似乎来自节点类child
方法。当在模型的self.beginRemoveRows
中调用removeRows
方法时,似乎会发生这种情况。奇怪的是,操作的顺序似乎是相反的,或者在模型知道它最近的更新之前,线程以某种方式导致刷新。
通过这些代码片段,我希望有人可以提供一个可能的解释或一些关于接下来要尝试调试的想法。
来自 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
答案 0 :(得分:4)
我花了一些时间,但我终于找到了错误的原因:根据index
方法中的mail,您应该在继续之前检查索引是否存在。令人讨厌的是,它没有写在method description,也没有写在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()
在我的申请中,这解决了这个问题。
答案 1 :(得分:0)
对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)