QAbstractItemModel index() 和 parent() 方法

Posted

技术标签:

【中文标题】QAbstractItemModel index() 和 parent() 方法【英文标题】:QAbstractItemModel index() and parent() methods 【发布时间】:2015-01-10 02:41:50 【问题描述】:

必须实现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() 返回具有给定索引的模型项的父项。如果项目没有父项,则返回无效的QModelIndex。公开树数据结构的模型中使用的一个常见约定是只有第一列中的项目有子项。对于这种情况,在子类中重新实现此函数时,返回的QModelIndex 的列将为0。在子类中重新实现此函数时,请注意避免调用QModelIndex 成员函数,例如QModelIndex::parent(),因为索引属于您的模型只会调用您的实现导致无限递归。

.index() 返回由给定行、列和父索引指定的模型中项目的索引。在子类中重新实现此函数时,调用 createIndex() 以生成模型索引,其他组件可以使用这些索引来引用模型中的项目。

值得一提的是,这两种方法都使用self.createIndex(row, column, dataVariable)方法。所以他们都做同样的事情:他们创建 QModelIndexes。我只是不明白为什么我们需要两种方法来做同样的事情!而且很难调试它,因为它们似乎在无限循环中运行......

【问题讨论】:

是什么阻止你阅读Qt documentation on the subject? 嗨,Ekhumoro! Qt 文档示例大多使用 C 语言(至少它的 MVC 教程)。 从无休止的测试中,我确实看到 .parent() 方法仅在*** QTableView 项目上调用。虽然为所有项目调用.index():***、二级子项目、三级孙项目等。我也确实看到两者都返回 QModelIndex,其中行、列和数据变量“链接”到它。看起来这两种方法返回的 QModelIndexes 应该是同步的。 .parent() 返回具有给定索引的模型项的父项。如果 item 没有父级,则返回无效的 QModelIndex。公开树数据结构的模型中使用的一个常见约定是只有第一列中的项目有子项。对于这种情况,在子类中重新实现此函数时,返回的 QModelIndex 的列将为 0。在子类中重新实现此函数时,请注意避免调用 QModelIndex 成员函数,例如 QModelIndex::parent(),因为索引属于到你的模型只会调用你的实现导致无限递归。 .index() 返回由给定行、列和父索引指定的模型中的项目的索引。在子类中重新实现此函数时,调用 createIndex() 以生成模型索引,其他组件可以使用这些索引来引用模型中的项目。 【参考方案1】:

这些方法是抽象定义的,以强制用户在子类化时实现它们。如果不实施它们,您的模型将无法工作,因为它们是定义模型结构所必需的。

通常当您想要创建分层模型时,您应该实现index()parent() 方法。对于表格和列表模型,在许多情况下,将QAbstractListModelQAbstractTableModel 子类化就足够了,它们具有这两种方法的默认实现。

简单地说,QAbstractItemModel.parent() 从子项返回父项QModelIndex,并且每当模型或视图需要为特定子项(或***项,如果parent 是无效的QModelIndex)。

【讨论】:

谢谢!如果出现这种需要,我会尝试设计一个可扩展 QTreeView 的模型。 我们可以说.parent() 方法用于“创建”***项目的QModelIndex。并且.index() 方法用于为***项目中的任何其他项创建 QModelIndex?或者这样的说法是错误的? @Sputnix 不,这是完全错误的。 index() 实际上用于创建模型中每个项目的QModelIndex。它可以是***项目或子项目。 parent() 用于返回任何项目的父项。在分层模型中,不同级别的许多项目都有父项,而只有***项目没有父项,因此应为其返回无效的 parent() 中的 QModelIndex 我确实看到了.parent() 方法的内部(在我的原始帖子#EDITED LATER 下):如果它是作为参数接收的***索引,则此方法仅返回QtCore.QModelIndex()。但是,如果它不是***项目,则此 .parent() 方法将继续并使用以下方法创建新的 QModelIndexself.createIndex(parentNode.row(), 0, parentNode) 其中parentNode 是“链接”到新创建的QModelIndex 的数据变量。所以......它确实创建了QModelIndexes......我真的迷失了我们使用的术语......例如“它返回”......从哪里返回?我真的很想了解 internalPointer() 返回与给定索引关联的数据结构。这是指向您在调用createIndex 时作为参数传递的数据的指针。

以上是关于QAbstractItemModel index() 和 parent() 方法的主要内容,如果未能解决你的问题,请参考以下文章

QAbstractItemModel - QModelIndex 对象在创建时是不是应该被缓存?

QAbstractItemModel Class

QAbstractItemModel::columnCount - 每行的可变列数

QTreeView 的 QAbstractItemModel:我做错了啥?

Qt:QAbstractItemModel 中的 setData 方法

在 QAbstractItemModel 中返​​回正数行和零列是不是可以?