use*_*527 3 c++ model-view-controller user-interface qt model
我有一个类用于永久存储某些项目,这些项目以表格方式组织.这个类与Qt完全无关,来自不同的库.让我们DataContainer
在这个问题的其余部分打电话给这个课程.它提供了与std-c ++兼容的迭代器来访问和操作内容.
我需要通过Qt GUI显示和修改数据.我的想法是创建一个DataContainerQtAdaptor
继承自QAbstractTableModel
并存储指向DataContainer
对象的指针的类.在DataContainerQtAdaptor
充当适配器的DataContainer
对象,并从我的Qt应用程序中的所有操作都通过该适配器来完成.然后我使用QTableView
小部件来显示信息.
不幸的DataContainer
是,线程/进程可能会改变它们.(例如,DataContainer
可以将某个C++类视为封装数据库连接,并且该数据库可能会被其他人更改.)
问题:
1)假设每次DataContainer
更改对象的内部结构时都会调用一个函数.QAbstractTableModel
必须调用的正确函数是什么,以通知模型的潜在变化?我需要像"亲爱的模型,您的持久存储后端已更改.请更新自己并向每个附加的视图发出信号以反映此更改".
2)让我们说1)解决了.在通过GUI触发更改的情况下,避免"双重"GUI更新的最佳方法是什么?例如:用户点击表格小部件中的单元格setData
- >模型的表格小部件调用- >模型将更改推送到后端 - >后端触发其自己的"onUpdate"功能 - >模型重新读取完整的后端(尽管它已经知道了更改) - > GUI第二次更新
3)用户应该能够通过GUI插入新的行/列并将数据放入其中.但是这个位置是由这个数据决定的,因为后端会保持数据的排序.因此,我有以下问题:用户决定在结尾创建一个新行,并将新数据推送到后端.重新读取后端/模型时,此数据通常不在最后位置,但已插入中间某处,所有其他数据已向前移动.我是否保持表格视图窗口小部件的所有属性,如"选择一个单元格"同步?
我相信,所有这些问题必须有一些简单的标准解决方案,因为它与QFileSystemModel
作品一样.用户选择文件,而其他一些进程创建新文件.新文件显示在视图中,所有后续行向前移动.选择也向前发展.
马蒂亚斯
首先,您必须确保QAbstractItemModel
不能处于不一致状态.这意味着在对基础数据进行某些更改之前,必须在模型上触发一些信号.
结构更改和数据更改之间存在根本区别.结构更改是要添加或删除的模型的行/列.数据更改仅影响现有数据项的值.
结构变化需要调用beginXxx
和endXxx
修改.在调用之前,您无法修改任何结构beginXxx
.完成更改结构后,请致电endXxx
.Xxx
是一个:InsertColumns
,MoveColumns
,RemoveColumns
,InsertRows
,MoveRows
,RemoveRows
,ResetModel
.
如果更改影响许多不连续的行/列,则表示模型重置更便宜 - 但要小心,视图上的选择可能无法生存.
保持结构完整的数据更改仅需要在修改基础数据后dataChanged
发送.这意味着在查询模型的对象收到之前可能会返回新值的调用时间窗口.data
dataChanged
这也意味着非常量模型在非QObject
类中几乎无用,除非您使用观察者或类似模式实现桥接功能.
在模型上处理更新循环的Qt惯用方法是利用项目角色.完全取决于您的模型如何解释角色.实现的简单而有用的行为QStringListModel
只是将角色从setData
调用转发到dataChanged
,否则忽略角色.
该股视图控件只反应到dataChanged
用DisplayRole
.然而,当他们编辑的数据,他们称之为setData
用EditRole
.这打破了循环.该方法适用于查看窗口小部件和Qt快速查看项目.
只要模型在排序完成后正确发出变化信号,你就可以了.
操作顺序是:
视图添加一行并调用模型的insertRow
方法.模型可以将此空行添加到底层容器中.关键是必须保留空行索引.
编辑从行中的项目开始.视图状态更改为Editing
.
在项目上完成编辑.视图退出编辑状态,并在模型上设置数据.
模型根据其内容确定项目的最终位置.
该模型调用beginMoveRows
.
该模型通过将项目插入正确的位置来更改容器.
该模型调用endMoveRows
.
在这一点上,一切都如你所愿.如果移动的项目在移动之前被聚焦,则视图可以自动跟随移动的项目.默认情况下,编辑的项目会被聚焦,因此工作正常.
除非通过模型完成对它的所有访问,否则您DataContainer
没有足够的功能来使其工作.如果要直接访问容器,请使容器明确继承,或者您必须向容器添加通知系统.前者是一个更容易的选择.QAbstractXxxxModel
您的核心问题简化为:我是否可以在不实现模型通知API的某些变体的情况下拥有模型功能.显而易见的答案是:不,对不起,你不能 - 按照定义.功能是存在,还是不存在.如果您不希望容器成为QObject
- 那么您可以使用观察者模式实现通知API - 那么您将需要模型填充类.真的没办法解决它.
将QFileSystemModel
得到大约已经改变个人目录条目文件系统通知.你的容器也必须这样做 - 这相当于提供dataChanged
某种形状或形式的信号.如果模型具有移动或添加/移除的项目 - 其结构发生变化 - 它必须通过调用相关和方法来发出xxxAboutToBeYyy
和发出xxxYyy
信号.beginZzz
endZzz
最重要的未记录方面QModelIndex
是:只要模型的结构没有改变,它的实例才有效.如果您的模型传递了一个在结构更改之前生成的索引,那么您可以自由地以未定义的方式行事(崩溃,发动核打击,无论如何).
存在的全部原因QModelIndex::internalPointer()
是您具有基础的,复杂索引的数据容器的用例.您对模型createIndex
方法的实现必须生成DataContainer
以某种形式存储对索引的引用的索引实例.如果这些索引适合指针,则无需在堆上分配数据.如果需要在堆上分配容器索引存储,则必须保留指向此数据的指针,并在容器的结构发生更改时将其删除.您可以自由地执行此操作,因为在结构更改后没有人应该使用索引实例.
归档时间: |
|
查看次数: |
4147 次 |
最近记录: |