qml中的嵌套列表:模型中的数据模型

Nested list in qml: data models in models

我正在尝试在 QML 界面中实现嵌套评论系统。我有一个 C++ 模型(subclass 来自 QAbstractListModel),其中模型中的每个项目 returns 有两个值:一个是 QString,另一个是角色名称为 "dataMap" 的 QVariantMap。这适用于 QML ListView。现在每个 QVariantMap 包含一个项目 "data",它进一步包含一个 QVariantList "children"。现在这基本上列出了具有相同结构的其他 QVariantMap。我实现这个的想法是在 QML ListView 中使用递归委托。下面是我的代码的最简单版本。

ListView{
    id: commentsList
    anchors.fill: parent
    model: commentsModel
    delegate: commentsDelegate
}
Component{
    id: commentsDelegate
    ColumnLayout{
        Rectangle{
            width: 600
            height: 200
            Text {
                id: bodyText
                text: dataMap.body
                anchors.centerIn: parent
                Component.onCompleted: console.debug(text)
            }
        }
        ListView{
            id: childList 

            property var childModel: dataMap.replies.data.children // QVariantList exposed to QML 

            x: 15
            interactive: false
            model: childModel
            anchors.fill: parent
            delegate: commentsDelegate
        }
    }
}

我的模型结构如下:

class ListModel : public QAbstractListModel
{
    Q_OBJECT
public:
   ListModel(){}
   explicit ListModel(QObject* parent =0);
   ~ListModel();


   QHash<int, QByteArray> roleNames() const;
   QVariant data(const QModelIndex & index, int role) const;
   int rowCount(const QModelIndex &parent) const;
   void addItem(ListItem item);
   void clearModel();
private:
   QList<ListItem> m_itemsList;
signals:
   void dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight);
};

ListItem class 只是

class ListItem
{

public:
    ListItem(QObject* parent = 0) : QObject(parent) {}
    virtual ~ListItem() {}

    ListItem(const QString & type, const QVariantMap & dataMap);
    QString type() const;
    QVariantMap dataMap() const;
private:
    QString m_type;
    QVariantMap m_dataMap;

现在由于多种原因这种方法不起作用(其中之一是 属性 dataMap 可以作为 data[= childModel 中的 25=],它在任何 QML 项目类型中被默认的 属性 data 覆盖)。这个问题有什么可能的解决方案吗?

我目前正在开发一个应用程序,它需要可视化大量(数亿 objects)树的孤立分支。因为是树,所以跟你的问题很像,就是嵌套模型。

我的解决方案是做一种抽象形式。由于树已经存在并且是与 GUI 完全不同的设计层,我使用代理 object,其中包含模型 class,它附加到可视化树节点。该模型只是列表视图访问底层数据的适配器。

该模型提供了一个 "object" 和一个 "type" 角色,"root" 委托使用它为 children 节点实例化一个 UI 元素,并且 object 角色用于创建一个代理以附加到每个 child,因此有效地,我得到了间接嵌套模型。

每个委托基本上都是一个加载器(虽然不是 Loader QML 元素),它从模型角色接收指向每个 object 及其类型的指针,因此它为此创建一个代理类型,以及附加到代理作为其数据源的 UI 元素 type + ".qml"

我不能分享任何代码,但希望你能明白。这种方法听起来有点复杂,但它提供了几个巨大的优势:

  • 繁重的 Qt object 只为需要的 object 创建
  • 多个UI元素可以共享同一个代理和模型
  • 单个代表可以创建任意数量的完全不同的 UI 元素
  • 它适用于具有任意数量的具有不同属性的不同类型的树,并且它仅使用两个角色来实现它。每个 object 都有其唯一的 UI 元素,可以通过代理访问底层 object 的所有数据。祝你好运,通过动态角色实现这一目标
  • 代理还用于通知每个UI每个底层object数据成员
  • 的数据变化

我发现这篇非常有用的文章帮助解决了问题https://lemirep.wordpress.com/2013/04/06/a-practical-case-exposing-qt-c-models-to-qml/。 该方法包括在模型 class 内创建另一个 ListModel(派生自 QAbstracListModel)。在我的示例中,我将 QVariantMap dataMap() 替换为另一个 ListModel dataModel()。请注意,这也需要进行其他更改(可以在提供的 link 中找到)