我从迁移QTreeWidget
到QtreeView
. 显而易见的和微不足道的事情在QTreeWidget
视图中似乎是不可能的。具体来说:我有一个带有树视图的主窗口。TreeView 使用我已经实现的模型,但不是直接的——通过QSortFilterProxyModel
它被设置为树的模型。现在,用户激活树中的一个项目,主窗口接收到一个信号itemActivated(QModelIndex item)
。我如何知道基础数据中的哪一项被激活了?数据是一个向量,因此使用 TreeWidget 我可以将项目的向量索引存储在 中QTreeWidgetItem
,但QModelIndex
甚至没有setData
API。
3 回答
我如何知道基础数据中的哪一项被激活了?
通过反转代理模型:
// supposing to connect this to your itemActivated signal
void onItemActivated(const QModelIndex &index)
{
QModelIndex originalIndex = proxyModel->mapToSource(index);
originalModel->doSomething(originalIndex);
}
您可以在源模型中定义自定义角色,返回基础数据或标识符(如果有)作为变体。这样做的好处是它可以与介于两者之间的任意数量的代理模型一起使用,因为数据将不加改变地通过模型传递,现在需要索引映射。
假设模型列出联系人,值结构/类Contact
保存数据。这需要Contact
通过 注册Q_DECLARE_METATYPE
。
class ContactModel ... {
...
enum Role {
ContactRole=Qt::UserRole,
ContactIdRole
};
QVariant data(...) const {
...
const Contact& contact = ...get from datastructure...
...
switch (role) {
...
case ContactRole:
return QVariant::fromValue( contact );
case ContactIdRole:
return contact.id;
}
}
...
在接收索引的代码中:
void SomeWidget::indexSelected(const QModelIndex& index)
{
const int id = index.data(ContactModel::ContactIdRole).toInt();
// look up Contact, do something with it
//or:
const Contact contact = index.data(ContactModel::ContactRole).value<Contact>();
// do something with the contact
...
}
索引可以来自联系人模型本身,也可以来自其之上的任何代理——这里的代码不必关心。
用于存储数据的模型。数据不再归QModelIndex
视图中的 items/ 所有。QModelIndex
只是在视图和模型之间传递的唯一标识符(在本例中是通过QSortFilterProxyModel
)。该模型应该继承QAbstractItemModel
其中有一些需要定义的纯虚函数(您可以从http://qt-project.org/doc/qt-4.8/itemviews-simpletreemodel.html复制样板文件)。例如,您必须QAbstractItemModel::data( const QModelIndex & index, int role = Qt::DisplayRole)
定义哪些数据对应于特定的QModelIndex
.
QSortFilterProxyModel 位于视图和模型之间,但不会改变模型的原则。有关如何处理QModelIndex
转换,请参阅此问题的其他答案。
总结:一旦你定义了它,QAbstractItemModel::data( const QModelIndex & index)
就会给你一个特定的数据。QModelIndex