【问题标题】:Declarative way to extend/concatenate multiple ListModel扩展/连接多个 ListModel 的声明式方法
【发布时间】:2019-05-09 11:34:56
【问题描述】:

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

示例: 列表模型(1):

COMMON A
COMMON B
COMMON C
A1
B1
C1

列表模型(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" }
    }
}

但似乎不可能,因为我收到以下错误:

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

【问题讨论】:

    标签: qt qml


    【解决方案1】:

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

    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&lt;ListModel&gt;,并将用法更改为

    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&lt;ListModel&gt;onOtherModelsChanged 的实现允许将多个模型“连接”到基本模型上。

    成功截图:

    正如augre所指出的,在只有一个模型被连接的情况下,您可以将属性简化为default property ListModel otherModel并拥有

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

    【讨论】:

    • 正是我试图实现的那种解决方法!很好地使用了默认属性。谢谢:)
    • 请注意,我不必使用list&lt;ListModel&gt; 默认属性。仅使用 default property ListModel 即可实现相同的行为,然后它还简化了下一个元素的添加:model.append(otherModels.get(j))
    • 另外,我意识到这允许创建多个链式ListModel 组件,每个组件都将自己的ListElements 添加到模型中,从而允许在另一个子组件中继续扩展模型。非常好!
    • 嗯...是的,你可以这样做default property ListModel。这适用于添加一个模型。 “我意识到这允许创建多个链式 ListModel 组件” 哈哈,是的,我测试了它是否可行(也在 github 演示中)。也许我的回答需要更多解释
    猜你喜欢
    • 1970-01-01
    • 2021-06-18
    • 2017-05-31
    • 1970-01-01
    • 2015-07-19
    • 2012-06-13
    • 1970-01-01
    • 2020-10-03
    • 2021-08-10
    相关资源
    最近更新 更多