中继器内的QML列表视图

QML ListView inside Repeater

本文关键字:列表 视图 QML 中继器      更新时间:2023-10-16

如何将不同的模型分配给位于Repeater内部的ListView?我画了一个草图(我的实际项目要大得多):

Column {
    Repeater {
        model: ["Line1","Line2","Line3","Line4"]
        Rectangle {
            ListView {
                model: ???
                delegate: Rectangle {
                    Text {
                        text: somemodelproperty
                    }                
                }
            }
        }
    }
}

目前,我正在通过复制粘贴10个矩形来解决这个想法,每个矩形都包含一个ListView。在C++中,我实现了10个QList<QObject*>,通过,每个列表都"绑定"到一个ListView

QQmlContext * example = engine.rootContext();
example->setContextProperty(modelname,QVariant::fromValue(listobject));

我很确定有一种更智能的方法可以做到这一点,但我几天前刚刚开始使用QML,无法找到解决方案。

问题是,不能将id用作列表元素的值,也不能在列表元素中嵌套列表模型,至少不能直接嵌套。

然而,你可以这样填充它:

Item {
    id: models
    ListModel {/*...*/}
    ListModel {/*...*/}
    //...
}
ListModel {
    id: outerModel
}
function set() {
    for (var i = 0; i < models.data.length; ++i) {
        outerModel.append({"model": models.data[i] /* and other stuff */})
    }
}

或者,如果您喜欢使用C++数据,可以向列表中的每个元素添加一个QObject*"模型"属性,并使用函数对其进行设置,如上例所示,也可以使用指定的内部模型的id

转念一想,你可能想用另一个名字而不是"模型",因为我无法想象QML会对model: model 这样的东西感到高兴

更新:您可以尝试这样做(假设您的10个模型在QML中显示为m1-m10

property var subModels: [m1, m2, ... m10]

然后,对于中继器代理内的ListView,您可以:

ListView {
    model: subModels[index]
    // ...
}

然后,假设中继器中有10个元素,则将从具有适当元素索引的数组中选择每个列表视图的模型。

声明中继器的模型,而不是使用字符串数组。您可以为此目的使用ListModel。您还可以向ListModels元素、ListElement添加任何您想要的属性。声明如下:

ListModel { 
   id: repeaterModel
   ListElement { title: "Line1"; model: modelForFirstElement; }
   ListElement { title: "Line2"; model: modelForSecondElement; }
   // ...
}

然后将其分配给中继器的型号属性

Repeater {
   id: repeater
   model: repeaterModel
// ...

然后,您可以通过调用模型的模型属性来访问ListView的模型,如下所示(假设您为repeater元素分配了id"repeater"):

ListView {
   model: repeater.model.model
// ...

对于模型,考虑一个嵌套有子数组的数组。为了区分,因为外部Repeater和内部ListView都具有不同的modelData实例,考虑将外部modelData复制到名为outerModelData的属性。

在下面的示例中,我重构出Column-Repeater-ListView,并将其替换为ListView-ListView。两种模式都能达到相同的效果,但后者做得更短。

import QtQuick
import QtQuick.Controls
Page {
    ListView {
        anchors.fill: parent
        model: [
            {la:"English",v:["one","two","three"]},
            {la:"Mandarin",v:["yi","er","san"]},
            {la:"French",v:["un","duex","trois"]},
            {la:"German",v:["eins","zwei","drei"]},
            {la:"Indonesian",v:["satu","dua","tiga"]},
        ]
        delegate: ListView {
            property var outerModelData: modelData
            width: 120
            height: childrenRect.height
            header: Text { text: outerModelData.la }
            model: outerModelData.v
            delegate: Frame {
                width: 100
                Text { text: modelData }                
            }
        }
    }
}

你可以在线试用!