下列问题与QAbstractItemModel
和QModelIndex
类的设计以及它们之间的相互作用有关,如下面的代码示例所突出显示的:
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/