下列问题与QAbstractItemModelQModelIndex类的设计以及它们之间的相互作用有关,如下面的代码示例所突出显示的:

class Data:
    def __init__(self):
        self.value = 42

class Model( QAbstractItemModel ):
    def __init__( self ):
        QAbstractItemModel.__init__(self)
        data = Data()

        modelIndex = self.createIndex( 1 , 2 , data ) ### 1
        self.index( 1 , 2 , QModelIndex() ) ### 2
        self.setData( modelIndex , data.value ) ### 3
        self.dataChanged.emit( modelIndex , modelIndex )

        modelIndex.data() ###4
        self.data( modelIndex ) ### 5



QModelIndex应该如何创建。根据我对文档的阅读,答案是QAbstractItemModel::createIndex(),但似乎不完整,因为此函数未提供任何有关ModelIndex与其父对象的偏移量的信息。而是由QAbstractItemModel::index()完成。有没有办法使两个功能一起发挥作用?
数据应如何存储在模型索引中或如何存储在模型索引中,以及由模型索引和internal pointer为其存储的数据或与之有关的数据之间有什么区别?当没有setData函数时,模型索引从哪里获得返回的data?内部指针曾经是数据吗?可能是数据吗?
ModelIndex和Model返回的数据有什么区别?即QModelIndex::data()QAbstractItemModel::data( QModelIndex , int )?为什么设置器QAbstractItemModel::setData( QModelIndex , ... )只是虚拟的,而获取器QAbstractItemModel::data( QModelIndex , ... )是纯虚拟的。该API当然应该能够返回其存储的数据。


我知道我的问题链接到C ++ API,而该代码段在PySide中。我这样做是因为这个问题涉及两个API。

最佳答案

考虑到您有许多与QAbstractItemModel和QModelIndex相关的问题,涉及到实现和其他设计的问题,我将花时间一一回答,因此我将编辑此答案以提供更多详细信息。

1。

QModelIndex没有其父级是谁的信息,也没有表示其偏移量的信息,它仅保留行,列,指向数据的指针及其所属模型的信息(请参见here)。因此,您知道您的父母是谁,这就是您的任务,因此您必须重写模型的parent()方法并将其返回。

def parent(self, index):
    if not index.isValid():
        return QtCore.QModelIndex()
    childItem = index.internalPointer()
    parentItem = childItem.parentItem()
    if parentItem == self.rootItem:
        return QtCore.QModelIndex()
    return self.createIndex(..., ..., parentItem)


因此,在QModelIndex的parent()方法中,该方法通过模型获取父对象(请参见here):def parent(self) : return self.model.parent(self)

关于index()createIndex()方法之间的关系,第二个方法由第一个方法调用,但也必须与您的数据结构有关系。通用实现是:

def index(self, row, column, parent):
    if not self.hasIndex(row, column, parent):
        return QtCore.QModelIndex()
    parentItem = None
    if not parent.isValid():
        parentItem = self.rootItem
    else:
        parentItem = parent.internalPointer()
    childItem = parentItem.child(...)
    if childItem is not None:
        return self.createIndex(row, column, childItem)
    return QtCore.QModelIndex()


在createIndex()的情况下,仅使用行,列,模型和指向childItem的指针的信息创建QModelIndex,该构造函数不在文档中,因为它是私有构造函数(请参见here)。

2。

internalPointer是一个变量,用于存储数据的内存位置,即QModelIndex没有数据,但是知道它在哪里,因此必须单独存储数据,因此当使用方法data()获得数据时对于模型,您必须获取internalPointer()来返回存储信息的项目,并根据该角色获取数据。

def data(self, index, role=QtCore.Qt.DisplayRole):
    if not index.isValid():
        return
    item = index.internalPointer()
    value = item.data(..., role) # like item.value
    return value


3。

QModelIndex的data()方法使用模型的data()方法(请参见here),因此从概念上讲它们是相同的,例如:def data(self, role): return self.model.data(self, role)

并非每个模型都是可编辑的,例如QStringListModel不是可编辑的,因此没有必要覆盖setData()方法,因此Qt默认使模型不可编辑,也就是说,它们什么也不做,并返回false(请参见here ),因此这意味着它必须是虚拟的,即仅在不重写此方法的情况下才会对其进行修改,并且如果不执行此操作,则将其称为父方法,即它将不执行任何操作。与data()方法不同,因为每个模型都必须返回信息,所以当开发人员从QAbstractItemModel继承该类时,必须迫使开发人员覆盖该类,因此将其声明为纯虚拟的。我建议您阅读,以便更详细地了解它们之间的区别:C++ Virtual/Pure Virtual Explained

关于python - QAbstractItemModel和QModelIndex之间的相互作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57128175/

10-10 07:37