在Qt中,我正在编写自己的树模型(通过子类化QAbstractItemModel
)来包装现有的数据结构。应该可以在内部(而不是通过模型)以及通过模型更新数据结构(因此视图可以更改它)。为了更好地想象它:它是一个场景图,应该可以使用场景视图进行编辑(不通过Qt模型),还可以使用一个大纲(QTreeView
,它使用Qt模型作为代理场景图。)
为避免混淆,我们应该考虑两种不同的场景(在下面,我以“删除”操作为例):
用户使用Qt视图删除节点。该视图要使用QAbstractItemModel::removeRow
从模型中删除一行。这应该依次从底层数据结构(场景图)中删除相应的节点。
用户使用场景视图删除节点。场景视图想要从场景图中删除节点。包围场景图的模型会得到通知,然后又想要通知已连接的视图刚刚删除了一行。
虽然我认为我知道如何实现1.我不知道如何在2中实现通知部分。有信号QAbstractItemModel::rowsAboutToBeRemoved()
以及rowsRemoved()
听起来像他们'我的朋友们但它们是私有信号(他们在标题源代码中说:“只能由QAbstractItemModel发出”)。还有beginRemoveRows()
和endRemoveRows()
但是根据他们的文档,当从视图中发生更新时,即在调用removeRow
时,应调用它们。此外,当我尝试使用它们时,视图完全搞砸了。
根据文档,似乎并不打算模型类可以为自修改数据建模。我们以文件系统为例。当使用文件系统监视(可以检测目录中的更改)时,模型应该通知视图,以便可以实时显示目录中的更改,即使视图未用于修改文件系统也是如此。这些模型甚至可以在Qt中使用吗?
答案 0 :(得分:1)
你读错了。当模型即将开始改变其“几何”时,模型必须向用户发出信号。因此,无论什么从模型中删除行,它必须告诉外界它发生了。视图从模型中删除行时的事件序列如下:
视图调用model->removeRows()
。
模型调用beginRemoveRows()
模型实际上会从内部数据中删除行。
模型调用endRemoveRows()
。
如果你实现了一些不会调用model->removeRows()
就会删除行的其他接口,你必须做同样的事情。如果它是一个视图或其他代码从模型中删除行,则无关紧要,模型的行为必须相同,否则什么都不会起作用。
您可以构建一个插入到SceneGraph和Model之间的适配器类。它应该保存一个指向场景图和模型的指针,并转换两者之间的操作。