我想知道在QML中实现以下功能的最佳方法:
我的 ListView 包含可放置元素,网格初始化为 DropArea 。 ListView使用从 QAbstractItemModel 派生的模型。我想在网格上放一个元素并与之交互(例如重命名)。目前,ListView中的任何修改都会更新模型,但网格中元素的修改如何更新模型?
网格中可能有多个项目与ListView模型的子集相对应。我不知道如何实现这一目标。无法使用包,因为网格不是GridView,必须在特定位置移动/设置项目。所以我试着:
我接近解决方案,但我认为这不是最好的方法。
有任何线索吗?
由于
答案 0 :(得分:0)
我想对同一模型有不同的视觉表现 ListView中的项目和Grid中的组件。所以,修改了 ListView中的项应该更新网格中的项目 反之亦然。
如果您的模型数据不是QObject
导出的NOTIFY
和属性,则只能通过模型进行更改通知。
由于您不会将该模型用于网格,这意味着您的模型必须使用基础QObject
实例。 A generic model object可能派上用场。
如果有,只需要引用基础QObject
模型项并使用绑定来设置列表视图委托。然后,当您拖放时,您只需要将对QObject
的引用传递给您将在网格中创建的其他可视化表示。
最后,当您从模型中删除项目时,请注意不要留下悬空引用,因为这很可能会使您的应用程序崩溃。当模型项目对象被销毁时,使用onDestruction
附加信号清除网格中的元素。
答案 1 :(得分:0)
我终于找到了一个解决方案,创建了一个C ++类型,它继承自QObject,可以嵌入到QML对象中。此类型具有读/写属性,并使用与ListView相同的模型进行初始化。有趣的方法是:
/* writing to a property **from QML** goes here */
void ModelItem::setName(const QString& name)
{
setModelData(GroupMemberModel::Nom, name);
}
/* then here */
bool ModelItem::setModelData(GroupMemberModel::Role role, const QVariant& value)
{
return m_model->setData(m_modelIndex, value, role);
}
/* any changes in the model fall here (signals/slots mecanism)*/
void ModelItem::dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles)
{
if(m_modelIndex.row() < topLeft.row() || m_modelIndex.row() > bottomRight.row())
return;
if(m_modelIndex.column() < topLeft.column() || m_modelIndex.column() > bottomRight.column())
return;
//Index is modified, emit signal
foreach(int role, roles) {
emitDataChanged(role);
}
}
/* **notify QML** by emit signal on property */
void ModelItem::emitDataChanged(int role) const
{
if(role < (Qt::UserRole+1))
role+=Qt::UserRole+1;
switch(role)
{
case GroupMemberModel::Nom:
emit nameChanged();
break;
default:
qDebug() << "ModelItem::dataChanged, unknown role";
break;
}
}
这可以根据需要运行,并且比我想象的更简单。