删除最后一行时出现pyqt树视图索引错误



我有一个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)

相关内容

  • 没有找到相关文章

最新更新