扩展/连接多个ListModel的声明方式

时间:2019-03-26 10:45:46

标签: qt qml

我想构建多个ListModel,它们都将从公共元素开始。 我想填充另一个ListModel中的其余元素。

示例: ListModel(1):

COMMON A
COMMON B
COMMON C
A1
B1
C1

ListModel(2):

COMMON A
COMMON B
COMMON C
A2
B2
C2

是否可以声明性地“合并”或扩展两个ListModel

到目前为止,我是动态进行的:

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    width: 480
    height: 320
    visible: true

    ListModel {
        id: commonModel
        ListElement { value: "COMMON A" }
        ListElement { value: "COMMON B" }
        ListElement { value: "COMMON C" }
    }

    ListModel {
        id: model1
        ListElement { value: "A1" }
        ListElement { value: "B1" }
        ListElement { value: "C1" }
    }

    ListModel {
        id: model2
        ListElement { value: "A2" }
        ListElement { value: "B2" }
        ListElement { value: "C2" }
    }

    ListView {
        anchors.fill: parent
        model: commonModel // here I would like to directly specify the "concatenated" model

        delegate: Text { text: model.value}

        // dynamic part that I want to avoid
        readonly property var additionalModel: model2
        Component.onCompleted: {
            for (var i = 0; i < additionalModel.count; ++i) {
                var elt = additionalModel.get(i)
                model.append(elt)
            }
        }
    }
}

编辑:换句话说,我想做些简单的事情:

// MyModel.qml
ListModel {
    ListElement { value: "COMMON A" }
    ListElement { value: "COMMON B" }
    ListElement { value: "COMMON C" }
}

能够根据需要在另一个组件中对其进行扩展:

ListView {
    model: MyModel {
        // keep original elements from MyModel and add custom "component-related" elements
        ListElement { value: "OTHER A" }
        ListElement { value: "OTHER B" }
        ListElement { value: "OTHER C" }
    }
}

但是由于我收到以下错误,所以这似乎是不可能的:

  

无法分配给不存在的默认属性

1 个答案:

答案 0 :(得分:2)

让我们从修补错误开始。它来自这里:

model: MyModel {
    ListElement { role_value: "OTHER A" }
    ListElement { role_value: "OTHER B" }
    ListElement { role_value: "OTHER C" }
}

要获得这种行为,您需要将MyModel的属性之一设置为default property。有点像

//  MyModel.qml
ListModel {
    default property list<ListElement> otherModels

    ListElement { role_value: "COMMON A" }
    ListElement { role_value: "COMMON B" }
    ListElement { role_value: "COMMON C" }
}

//  Main.qml
import QtQuick 2.0
import QtQuick.Window 2.2

Window {
    ListView {
        model: MyModel {
            // these should be auto-assigned to the default property      
            ListElement { role_value: "OTHER A" }
            ListElement { role_value: "OTHER B" }
            ListElement { role_value: "OTHER C" }
        }
    }
}

通常,对于其他类型,这可以正常工作。但是ListElement是一个特例。如果您尝试执行上述操作,则可能会收到错误消息:

  

无法分配给不存在的属性“ role_value”

Documentation提示ListElements只能在ListModels下定义。据我所知,这似乎是唯一可行的解​​决方法。这意味着将默认属性更改为list<ListModel>,并将用法更改为

ListView {
    model: MyModel {
        // ListModel is auto-assigned to the default property
        ListModel {
            ListElement { role_value: "OTHER A" }
            ListElement { role_value: "OTHER B" }
            ListElement { role_value: "OTHER C" }
        }
    }
}

这是一个最小而完整的示例:

//  MyModel.qml
import QtQuick 2.0

ListModel {
    id: model
    default property list<ListModel> otherModels

    ListElement { role_value: "COMMON A" }
    ListElement { role_value: "COMMON B" }
    ListElement { role_value: "COMMON C" }

    //  called everytime a model is append to otherModels
    onOtherModelsChanged: {
        //  add ListElements from the last otherModels to this model
        var i = otherModels.length - 1;
        if (i < 0) return;

        for (var j = 0; j < otherModels[i].count; j++)
            model.append(otherModels[i].get(j));
    }
}


//  Main.qml
import QtQuick 2.6 
import QtQuick.Window 2.2      //  Window
import QtQuick.Controls 2.2    //  ItemDelegate

Window {
    visible: true
    width: 640
    height: 480

    ListView {
        anchors.fill: parent
        model: MyModel {
            ListModel {
                ListElement { role_value: "OTHER A" }
                ListElement { role_value: "OTHER B" }
                ListElement { role_value: "OTHER C" }
            }
        }

        delegate: ItemDelegate {
            text: role_value
            width: parent.width
        }
    }
}

See a more sophisticated demo on Github.

default property list<ListModel>onOtherModelsChanged的实现允许将多个模型“连接”到基本模型上。

成功的屏幕截图:

enter image description here

augre所述,如果仅串联了 一个 模型,则可以将该属性简化为default property ListModel otherModel并具有

onOtherModelChanged: {
    if (otherModel === undefined) return;
    for (var i = 0; i < otherModel.count; i++)
        model.append(otherModel.get(i));
}