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

2022-01-02 00:00:00 qt qml listview c++ models

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

I am trying to implement a nested comment system in a QML interface. I have a model in C++ (subclassed from QAbstractListModel) in which each item in the model returns two values: one is a QString and the other is a QVariantMap with roleName "dataMap". This works fine with a QML ListView. Now each QVariantMap contains an item "data" which further contains a QVariantList "children". Now this lists basically other QVariantMaps with the same structure. My idea to implement this was to use a recursive delegate in a QML ListView. Below is the simplest version of my code.

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 类很简单

The ListItem class is simply

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 可以作为 childModel 中的 data 访问>,它被任何 QML 项目类型中的默认属性 data 覆盖).这个问题有什么可能的解决方案吗?

Now this approach does not work for a number of reasons (one of which is that the property dataMap is accessible as data in the childModel, which is overridden by the default property data in any QML Item type). Any possible solution to this problem?

推荐答案

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

I have found this very useful article that helped to solve the problem https://lemirep.wordpress.com/2013/04/06/a-practical-case-exposing-qt-c-models-to-qml/. The approach consists into creating another ListModel (derived from QAbstracListModel) inside the model class. In my example, I replace QVariantMap dataMap() with another ListModel dataModel(). Notice that this requires other changes too (which can be found at the link provided)

相关文章