需要实现QAbstractItemModel.parent()
方法,否则会出现这个令人讨厌的错误:
NotImplementedError: QAbstractItemModel.parent() is abstract and must be overridden
除了.parent()
之外,index()
方法也需要被覆盖或面对:
NotImplementedError: QAbstractItemModel.index() is abstract and must be overridden
问题:两种方法的目的是什么?它们的工作方式有何不同?
.parent()
方法的示例:
def getNodeFromIndex(self, index):
if index.isValid():
node = index.internalPointer()
if node:
return node
return self.items
def parent(self, index):
node = self.getNodeFromIndex(index)
parentNode = node.getParent()
if parentNode == self.items:
return QtCore.QModelIndex()
return self.createIndex(parentNode.row(), 0, parentNode)
关于.index()
方法的示例:
def index(self, row, column, parentIndex):
parentNode = self.getNodeFromIndex(parentIndex)
childNode = parentNode.getChildren(row)
if childNode:
newIndex=self.createIndex(row, column, childNode)
return newIndex
else:
return QtCore.QModelIndex()
从无休止的测试中,我确实看到.parent()
方法仅在顶级QTableView
项上调用。虽然.index()被调用所有项目:顶级,二级子项目,三级孙子项目等。我也看到两者都返回QModelIndex
行,列和数据变量“链接”到它。看起来两个方法返回的QModelIndexes应该是同步的。
.parent()
返回具有给定索引的模型项的父级。如果item没有父项,则返回无效的QModelIndex
。在公开树数据结构的模型中使用的常见约定是只有第一列中的项目具有子项。对于这种情况,当在子类中重新实现此函数时,返回的QModelIndex
的列将为0.在子类中重新实现此函数时,请小心避免调用QModelIndex
成员函数,例如{{ 1}},因为属于您的模型的索引将简单地调用您的实现,从而导致无限递归。
QModelIndex::parent()
返回给定行,列和父索引指定的模型中项的索引。在子类中重新实现此函数时,调用.index()
生成模型索引,其他组件可以使用它来引用模型中的项目。
值得一提的是,这两种方法都使用createIndex()
方法。所以他们都做同样的事情:他们创建QModelIndexes。我只是不明白为什么我们需要两种方法来做同样的事情!并且它很难调试,因为它似乎在无限循环中运行....
答案 0 :(得分:4)
这些方法被定义为abstract,以强制用户在子类化时实现它们。如果没有实现它们,你的模型将无法工作,因为它们是定义模型结构所必需的。
通常,当您想要创建分层模型时,您应该实现index()
和parent()
方法。对于表和列表模型,在许多情况下,它足以继承QAbstractListModel
和QAbstractTableModel
,它们具有两种方法的默认实现。
简单来说,QAbstractItemModel.parent()
会从子项返回父QModelIndex
,只要模型或视图需要为特定子项创建QAbstractItemModel.index()
,就会调用QModelIndex
(如果父项是无效的QModelIndex
,则为顶级项目。)