简体   繁体   English

如何在 QML ListView 和 Grid 之间共享模型的项目

[英]How to share a model's item between a QML ListView and a Grid

I would like to know the best way to achieve the following thing in QML:我想知道在 QML 中实现以下内容的最佳方法:

I have a ListView with droppable elements and a Grid initialy filled with DropArea .我有一个带有可放置元素的ListView和一个填充DropAreaGrid初始 The ListView uses a model derived from QAbstractItemModel . ListView 使用从QAbstractItemModel派生的模型。 I would like to drop an element on the grid and interact with it (rename it for instance).我想在网格上放置一个元素并与之交互(例如重命名)。 For now, any modifications in the ListView update the model, but how modifications of the element in the grid could update the model ?目前,ListView 中的任何修改都会更新模型,但是网格中元素的修改如何更新模型?

There can be multiple items dropped in the grid corresponding to a subset of ListView's model.在对应于 ListView 模型子集的网格中可以有多个项目。 I do not know how can I achieve this.我不知道我怎样才能做到这一点。 The Package can not be used because the Grid is not a GridView and Items must be moved/set at specific positions.无法使用包,因为网格不是 GridView,必须在特定位置移动/设置项目。 So I tried to:所以我试图:

  • create a ListView displayed on the dropped item, using the same model as the source ListView used to drag items,创建一个显示在拖放项上的 ListView,使用与用于拖动项的源 ListView 相同的模型,
  • set the same rootIndex, then the same index设置相同的 rootIndex,然后相同的索引

I am close to a solution but I think it is not the best way to do this.我接近解决方案,但我认为这不是最好的方法。

Any clue ?任何线索?

Thanks谢谢

I would like to have different visual representation of the same model item in a ListView and in a component in a Grid.我希望在 ListView 和网格中的组件中具有相同模型项的不同视觉表示。 So, a modification of the item in the ListView should update the item in the Grid and vice-versa.因此,对 ListView 中项目的修改应该更新 Grid 中的项目,反之亦然。

If your model's data is not QObject derived with NOTIFY and properties, notifications of changes can only be made through the model.如果您的模型数据不是通过NOTIFY和属性派生的QObject ,则更改通知只能通过模型​​进行。

And since you won't be using the model for the grid, that means your model has to use underlying QObject instances.并且由于您不会将模型用于网格,这意味着您的模型必须使用底层QObject实例。 A generic model object might come in handy. 通用模型对象可能会派上用场。

When you have that you only need to reference the underlying QObject model item and use bindings to set up your list view delegate.当您拥有它时,您只需要引用底层QObject模型项并使用绑定来设置您的列表视图委托。 Then when you drag and drop, you only need to pass a reference to the QObject to that other visual representation which you will be creating inside the grid.然后当您拖放时,您只需要将QObject的引用传递给您将在网格内创建的其他视觉表示。

Lastly, take care not to be left with dangling references when you remove items from the model, as that will most likely hard-crash your application.最后,当您从模型中删除项目时,请注意不要留下悬空引用,因为这很可能会使您的应用程序崩溃。 Use the onDestruction attached signal to clear elements from the grid as the model item objects are destroyed.当模型项对象被销毁时,使用onDestruction附加信号从网格中清除元素。

I finally found a solution by create a C++ type which inherits from QObject an which can be embedded in a QML object.我终于通过创建一个 C++ 类型找到了一个解决方案,该类型继承自 QObject an 可以嵌入到 QML 对象中。 This type has read/write properties and is initialized with the same model as the ListView.此类型具有读/写属性,并使用与 ListView 相同的模型进行初始化。 The interesting methods are:有趣的方法是:

/* 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;
    }
}

This works as needed and is simplier than what I thought.这可以根据需要工作,并且比我想象的更简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM