ComboBox 内的 Qt Quick Checkbox 创建 Surface3D 系列

Qt Quick Checkbox inside ComboBox to create Surface3D series

我正在使用 Qt qmlsurfacelayers 示例。我添加了一个带有复选框的组合框。我的计划是使用复选框状态来添加和删除 Surface3Dseries。我的想法是 ListElement 中的“名称”属性将是 Surface3D 系列的 ID,我可以使用 addSeries/removeSeries 来实现我的目标。

然而,当我选中第一个框时,surfaceLayers.addSeries(name) 未评估为 surfaceLayers.addSeries(layerOneSeries)

        ComboBox {
        id: comboboxId
        width: parent.width / 2
        height: 50
        displayText: "Grids"
        model: surflist
        delegate: Item {
            width: parent.width
            height: 50
            Row {
                spacing: 5
                anchors.fill: parent
                anchors.margins: 5
                CheckBox {
                    id: cahc
                    height: parent.height
                    width: height
                    checked: ischecked
                    onCheckedChanged: {
                        if(checked)
                        {
                            //here to load surface
                            surfaceLayers.addSeries(name);
                        }
                        else if (!checked){
                            console.log(name.visible)
                            surfaceLayers.removeSeries(name);
                        }

                    }
                }
                Label {
                    text: name
                    width: parent.width - cahc.width
                    height: parent.height
                    verticalAlignment: Qt.AlignVCenter
                    horizontalAlignment: Qt.AlignHCenter
                }
            }
        }
    }
    ListModel {
        id:surflist
                    ListElement { name: "layerOneSeries"; file: "red"; ischecked: true }
                    ListElement { name: "Two"; file: "green"; ischecked: false }
                    ListElement { name: "Three"; file: "blue"; ischecked: true }
                }
    Surface3DSeries {
        id: layerOneSeries
        flatShadingEnabled: false
        drawMode: Surface3DSeries.DrawSurface
        baseGradient: layerOneGradient
        ItemModelSurfaceDataProxy {
            itemModel: surfaceData.modelName
            rowRole: "longitude"
            columnRole: "latitude"
            yPosRole: "height"
        }
        //! [4]
        visible: true // bind to checkbox state
        //! [4]
    }

这是行不通的,因为您将对象的 ID 作为字符串传递,但您确实有兴趣传递对对象本身的引用。这是有问题的,原因有二; ListModels 不能包含对对象(例如 id 的引用),其次是因为 id 不能在运行时通过字符串访问。不过,您可以通过其他方式完成此操作。

QML 使用 objectName 这是一个可用于查找对象的字符串。使用它的一种方法是迭代分组对象并通过 objectName 匹配来识别它们。我已经创建了一个简化版本的代码,它切换了一些矩形的可见性来演示:

Column {

    Repeater {
        model: ListModel {
            ListElement { name: "layerOneSeries"; file: "red"; ischecked: true }
            ListElement { name: "two"; file: "green"; ischecked: false }
        }

        delegate: CheckBox {
            text: name
            checked: ischecked

            onCheckedChanged: {
                var object = getObject(name)
                if (checked) {
                    addSeries(object); // pass returned object by reference to addSeries()
                } else if (!checked) {
                    removeSeries(object);
                }
            }
        }
    }

    Column {
        id: itemsContainer // arbitrary container to enable getObject() iteration

        Rectangle {
            objectName: "layerOneSeries" // objectName set to match string in ListElement, id not necessary in this example
            color: "red"
            height: 30
            width: 30
            visible: false
        }

        Rectangle {
            objectName: "two"
            color: "green"
            height: 30
            width: 30
            visible: false
        }
    }
}

function addSeries(object) {
    // as object was passed by reference, we can directly manipulate it
    object.visible = true
}

function removeSeries(object) {
    object.visible = false
}

function getObject (name) {
    // iterate over itemsContainer children to find and return the object with matching string objectName (not id)
    for (let i = 0; i < itemsContainer.children.length; i++) {
        if (itemsContainer.children[i].objectName === name) {
            return itemsContainer.children[i]
        }
    }
}