pyqt treeview 删除最后一行时报索引错误
我有一个两列的树形视图,结构很简单,只有两层:根节点 > 父节点 > 子节点。当我按下删除键时,我在树形视图的子类中有一个删除行的调用。删除任何行时,这个功能都能正常工作,但删除最后一行时就出问题了。
我遇到了一个错误,提示 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
2 个回答
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)
4
我花了一些时间,终于找到了这个bug的原因:根据这封邮件,在使用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()
在我的应用中,这样做解决了问题。