向 Qt 树模型添加一些自定义数据

Posted

技术标签:

【中文标题】向 Qt 树模型添加一些自定义数据【英文标题】:Adding some custom data to the Qt tree model 【发布时间】:2009-06-04 08:20:16 【问题描述】:

我是在 Qt 中使用模型/视图范例的菜鸟,并且有以下问题:我有一个树状结构,必须通过 Qt 可视化。我发现 QAbstractTableModel 非常适合我的需求,所以我写了以下内容:

class columnViewModel : public QAbstractTableModel 
   // some stuff...
;

现在一切正常,但现在我必须在树的节点上实现“观察者”设计模式。每当节点在 TreeView 中展开时,我必须在相应的节点上添加一个观察者。每当节点崩溃时,我必须从节点中删除这个观察者。所以,我写了一些东西,像这样:

void onExpand( const QModelIndex & Index ... ) 
   Node* myNode = static_cast<Node*>(Index->internalPointer());
   Observer* foo = Observer::create();
   myNode->addObserver(foo);

   // ok up to here, but now where can I save this Observer? I must associate 
   // it with the Node, but I cannot change the Node class. Is there any way 
   // to save it within the index?


void onCollapse( const QModelIndex & Index ... ) 
   Node* myNode = static_cast<Node*>Index->internalPointer();
   Observer* foo = // well, what should I write here? Node does not have anything 
                   // like "getObserver()"! Can I extract an Observer from Index?

   myNode->remObserver( foo );

我现在没有 sn-ps,所以代码可能不是有效的 Qt,但问题似乎很清楚。我既不能改变 Node 也不能改变 Observer 类。我可以有一个观察者的内部列表,但是我必须解决从特定节点中删除的观察者。有什么方法可以将 Observer 指针保存在 Index 中(可能是一些用户数据),以便在 onCollapse 中快速解决它?欢迎任何想法......

【问题讨论】:

【参考方案1】:

执行以下操作:

定义一个新角色(类似于Qt::UserRole),比如说ObserverRole。

使用 QAbstractItemModel::setData 来 将观察者设置为数据 观察者角色。代码草图:

this->model()->setData(ObserverRole, QVariant::fromValue(foo));

您可能需要在 cpp 实现文件中放入元数据声明,例如

Q__DECLARE __METATYPE ( 观察者* );

允许 QVariant 以适当的方式进行变体强制转换。

您可以使用具有观察者角色的 QModelIndex::data 获取索引的观察者:

index.data(ObserverRole);

在您的模型实现中,添加对 Observer 角色(如果有)返回数据的支持(就像您可能对 Qt::UserRole 或 Qt::DisplayRole 所做的那样。

收到评论的更新:

通常,QModelIndex::data 为查看者提供数据。请求数据时指定的角色允许模型的定制者出于不同的原因提供不同的数据(例如,为显示角色提供字符串 -> 项目的标题)。

如果你不使用这种机制来获取数据,那么你可能不需要 QTreeView。在这种情况下,使用 QTreeWidget,您可以直接使用 QTreeWidgetItems 并通过 setData 方法将数据附加到项目,或者将 QTreeWidgetItem 子类化并将数据添加为该子类的成员。

视图通常在您想要使用模型时使用。

【讨论】:

这听起来像是解决方案,但我有问题,实施最后一部分。每当我定义 Qt::DisplayRole 时,我都会从索引中获取 internalPointer(),它实际上是一个节点。当我定义 ObserverRole 时,无论如何我都不能使用 internalPointer(),现在我想,我必须切换到某个 struct ,在其中保留 Node 及其 Observer。我将能够将 index internalPointer() 类型转换为该结构左右...... 感谢您的想法。我现在明白了,这不是 Qt 模型的问题,而是我的观察者/节点范式的问题。我应该做一些编码来创建一个哈希,这将允许我解析哪个观察者属于特定节点。

以上是关于向 Qt 树模型添加一些自定义数据的主要内容,如果未能解决你的问题,请参考以下文章

自定义 Qt 设计器小部件:包含自定义垂直布局的滚动区域

26.QT-模型视图之自定义委托

从 DOM 中读取 HTML 片段并向其中添加自定义数据

向用户 ASP.NET 身份添加自定义角色

Qt - 我自己的自定义对象的 QListView

Qt之模型/视图(自定义按钮)