如何根据 属性 向 DelegateModelGroup 添加元素

How to add elements to a DelegateModelGroup depending on a property

我有一个 ListModel 和一个 DelegateModel、一个 ListView 和 3 个按钮。 DelegateModel 有一个组:myGroup 通过单击前两个按钮,我将具有不同属性的元素添加到 ListModel,然后将使用这些元素将它们添加或不将它们添加到 myGroup。第三个按钮用于切换过滤器。

ListModel {
    id: rootModel
}


DelegateModel {
    id: visualModel
    model: rootModel
    groups: [DelegateModelGroup { name: 'myGroup' }]

    delegate: Rectangle {
        width: model.width
        height: model.height
        color: model.color
        border.width: 1

        Component.onCompleted: DelegateModel.inMyGroup = Qt.binding(function() {return width == 80})
    }
}

ListView {
    width: 300
    height: 480
    model: visualModel
}

Rectangle {
    id: b1
    x: 350
    width: 100
    height: 50
    color: 'lightsteelblue'
    Text {
        anchors.centerIn: parent
        text: 'add 80'
    }

    MouseArea {
        anchors.fill: parent
        onClicked: rootModel.append( { width: 80, height: 30, color: 'steelblue' })
    }
}

Rectangle {
    id: b2
    x: 350
    y: 70
    width: 100
    height: 50
    color: 'violet'
    Text {
        anchors.centerIn: parent
        text: 'add 50'
    }

    MouseArea {
        anchors.fill: parent
        onClicked: rootModel.append( { width: 50, height: 30, color: 'violet' })
    }
}
Rectangle {
    id: b3
    x: 350
    y: 140
    width: 100
    height: 50
    color: 'green'
    Text {
        anchors.centerIn: parent
        text: 'filter'
    }

    MouseArea {
        anchors.fill: parent
        property bool toggle: false
        onClicked: {
            visualModel.filterOnGroup = toggle ? '' : 'myGroup'
            toggle = !toggle
        }
    }
}

到目前为止一切顺利,只要不设置过滤器,我就可以将两种类型的元素添加到模型中,然后我就可以过滤了。 但是,只要设置了过滤器,我就无法将元素添加到模型(组)中。这很明显,默认情况下不添加元素,因此组件没有完成,也没有向组中添加任何内容,直到我再次取消设置过滤器,所有待处理的元素都被实例化、完成并最终添加。

因此我寻找另一种方法来自动将依赖于 属性 的元素添加到组中,或排除它们。

我知道,我可以设置 includeByDefault: true 然后在实例化一次后将它们扔掉。虽然这解决了这个特定问题,但并没有解决下一个问题,我将在其中更改 属性,因此将其从组中删除,然后再将其更改回来。它不会重新出现,直到组件再次重​​新实例化。

哦,我知道,我可以用 C++ 解决这个问题,但我不想这样做,除非有必要。

问题是 DelegateModel.inMyGroup = Qt.binding(function() {return width == 80}) 仅在对象显示后才被评估。但是当过滤器打开时,如果添加了一个元素,它不属于 myGroup 组,因此它不会显示并且永远没有机会评估条件。

这是一个快速修复方法,我添加了一个函数,每次添加元素时都会执行该函数。默认组似乎是 'items' 而不是 ''.

Window {
    visible: true
    width: 640
    height: 480
    property bool toggle: true


    ListModel{
        id: rootModel
        onCountChanged: visualModel.setGroups()
    }

    DelegateModel {
        id: visualModel
        model: rootModel
        filterOnGroup: toggle ? 'items' : 'myGroup'
        groups: [DelegateModelGroup { id: myGroup; name: 'myGroup' }]

        function setGroups() {
            var newItem = rootModel.get(rootModel.count - 1)
            var groups;
            if (newItem.width == 80){
                groups = ['items', 'myGroup'];
            }else{
                groups = ['items'];
            }
            items.setGroups(rootModel.count - 1, 1, groups)
        }

        delegate: Rectangle {
            width: model.width
            height: model.height
            color: model.color
            border.width: 1
        }
    }

    ListView {
        width: 300
        height: 480
        model: visualModel
    }

    Rectangle {
        id: b1
        x: 350
        width: 100
        height: 50
        color: 'lightsteelblue'
        Text {
            anchors.centerIn: parent
            text: 'add 80'
        }

        MouseArea {
            anchors.fill: parent
            onClicked: rootModel.append( { width: 80, height: 30, color: 'steelblue' })
        }
    }

    Rectangle {
        id: b2
        x: 350
        y: 70
        width: 100
        height: 50
        color: 'violet'
        Text {
            anchors.centerIn: parent
            text: 'add 50'
        }

        MouseArea {
            anchors.fill: parent
            onClicked: rootModel.append( { width: 50, height: 30, color: 'violet' })
        }
    }
    Rectangle {
        id: b3
        x: 350
        y: 140
        width: 100
        height: 50
        color: 'green'
        Text {
            anchors.centerIn: parent
            text: 'filter'
        }

        MouseArea {
            anchors.fill: parent
            onClicked: {
                toggle = !toggle
            }
        }
    }
}

对于那些对此感兴趣的人,在 user2436719 的提示下,我能够破解这个模型。 它是一个 ListModel,例如两个 DelegateModel,根据 listmodel 的角色向其添加元素的组。

ListModel{
    id: rootModel
    onCountChanged: setGroups(count - 1)
    onDataChanged: setGroups(arguments[0].row)
    property DelegateModel sub1:
        DelegateModel {
            id: subModel1
            model: rootModel
            groups: [
                DelegateModelGroup { name: 'myGroup' },
                DelegateModelGroup { name: 'notMyGroup' }
            ]
            delegate: Rectangle {
                width: model.width
                height: model.height
                color: model.color
                border.width: 1
            }
            filterOnGroup: (root.toggle ? 'myGroup' : 'notMyGroup')
        }
    property DelegateModel sub2:
        DelegateModel {
            id: subModel2
            model: rootModel
            groups: [
                DelegateModelGroup { name: 'myGroup' },
                DelegateModelGroup { name: 'notMyGroup' }
            ]
            delegate: Rectangle {
                radius: 5
                width: model.width
                height: model.height
                color: model.color
                border.width: 1

                Text {
                    anchors.centerIn: parent
                    text: DelegateModel.groups.toString()
                }
            }
            filterOnGroup: (root.toggle ? 'myGroup' : 'notMyGroup')
        }

    function setGroups(index) {
        console.log('set Groups for', index)
        var i = get(index)
        subModel1.items.setGroups(index, 1, ['items', (i.width === 80 ? 'myGroup' : 'notMyGroup')])
        subModel2.items.setGroups(index, 1, ['items', (i.width !== 80 ? 'myGroup' : 'notMyGroup')])
    }
}