在 QML 中,(如何)我可以将 MapItemGroup 作为 MapItemView 的委托组件?

In QML, (how) can I make MapItemGroup as a MapItemView's delegate component?

情况: 我可以将 QML 地图项与 Model/View/delegate 一起使用。我可以处理单个项目。

问题: 作为下一步,我希望能够绘制多个项目。我需要在单个委托组件中放置多个 QML MapItems(如 MapCircleMapRectangle 等)。通常,QML 支持一个委托中的多个项目。问题在于 MapItemView 的委托:它不支持多个子项。

我的方法:

  1. 我认为使用 MapItemGroup 会奏效。但似乎我错过了什么。关于如何使它作为委托组件工作的文档也不是很详尽。附加的片段显示了这个实现。

    Qt's Documentation on MapItemGroup

在下面的代码中:

一个简单的实现:

import QtQuick 2.10
import QtPositioning 5.6
import QtLocation 5.9
import QtQuick.Controls 2.3 as QQc2

QQc2.ApplicationWindow {
    visible: true
    width: 640
    height: 480
    // Some list model
    ListModel {
        id: someModel
        ListElement {lat: 0; lon: 0}
        ListElement {lat: 5; lon: 0}
        ListElement {lat: 5; lon: 5}
        ListElement {lat: 0; lon: 5}
    }

    Map {
        id: map
        anchors.fill: parent
        plugin: Plugin {name: "osm"}
        center: QtPositioning.coordinate(2.5, 2.5)
        zoomLevel: 6

        // Some views to test the model
        // delegateCircle, delegateRect work fine
        // delegateGroup is not displayed 
        MapItemView {
            model: someModel
            delegate: MapCircle {
                id: delegateCircle
                border.color: "red"
                border.width: 1
                center: QtPositioning.coordinate(model.lat, model.lon)
                radius: 50*1000
            }
        }

        MapItemView {
            model: someModel
            delegate: MapRectangle {
                id: delegateRect
                border.color: "green"
                border.width: 3
                topLeft     : QtPositioning.coordinate(model.lat+1, model.lon-1)
                bottomRight : QtPositioning.coordinate(model.lat-1, model.lon+1)
            }
        }

        MapItemView {
            model: someModel
            delegate: MapItemGroup {
                id: delegateGroup
                MapCircle {
                    id: innerCircle
                    border.color: "green"
                    border.width: 3
                    center: QtPositioning.coordinate(model.lat, model.lon)
                    radius: 75*1000
                }

                MapRectangle {
                    id: innerRect
                    border.color: "red"
                    border.width: 6
                    topLeft     : QtPositioning.coordinate(model.lat+2, model.lon-2)
                    bottomRight : QtPositioning.coordinate(model.lat-2, model.lon+2)
                }
            }
        }
    }
}

以上代码的输出为:

  1. 我还尝试使用 MapItemGroup 作为 MapQuickItem 类型的 sourceItem。这也没有用。

我想达到的目标:

嗯。我需要使用 MapItemView 绘制多个地图项。欢迎任何其他 solution/method(包括 c++ 后端程序)。

编辑

谢谢@GrecKo 和@Yoann。您的两种解决方案都有效。但是,我选择继续使用 Instantiator,因为它更适合我的应用程序。

在看到您的解决方案后,我也发现这个很有趣:a developer's discussion on populating a model using Repeater and Instantiator

您可以使用简单的 Repeater 而不是 MapItemView

import QtQuick 2.10
import QtPositioning 5.6
import QtLocation 5.9
import QtQuick.Controls 2.3

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    // Some list model
    ListModel {
        id: someModel
        ListElement {lat: 0; lon: 0}
        ListElement {lat: 5; lon: 0}
        ListElement {lat: 5; lon: 5}
        ListElement {lat: 0; lon: 5}
    }

    Map {
        id: map
        anchors.fill: parent
        plugin: Plugin {name: "osm"}
        center: QtPositioning.coordinate(2.5, 2.5)
        zoomLevel: 6

        Repeater
        {
            model: someModel
            MapItemGroup {
                id: delegateGroup
                MapCircle {
                    id: innerCircle
                    border.color: "green"
                    border.width: 3
                    center: QtPositioning.coordinate(model.lat, model.lon)
                    radius: 75*1000
                }

                MapRectangle {
                    id: innerRect
                    border.color: "red"
                    border.width: 6
                    topLeft     : QtPositioning.coordinate(model.lat+2, model.lon-2)
                    bottomRight : QtPositioning.coordinate(model.lat-2, model.lon+2)
                }

                Component.onCompleted: map.addMapItemGroup(this)
            }
        }
    }
}

正如 GrecKo 指出的那样,为了使其与动态模型一起使用,必须将 itemGroup "manually" 添加到地图中,因此 Component.onCompleted: map.addMapItemGroup(this)

不幸的是,MapItemView 仅适用于 MapItem 衍生项目,MapItemGroup 不是其中之一。

您可以使用 Repeater,它适用于从一开始就创建的委托,但如果您稍后在模型中添加行,它将不起作用。 我在 中解释了为什么 Repeater 不太适合 Map

在我的回答中,我建议使用 MapItemView 但它在这里不适用。 希望还有最后一个可用的解决方案:
Instantiator with Map.addMapItemGroup() and Map.removeMapItemGroup().

import QtQuick 2.10
import QtPositioning 5.6
import QtLocation 5.9
import QtQuick.Controls 2.3 as QQc2
import QtQml 2.2

QQc2.ApplicationWindow {
    visible: true
    width: 640
    height: 480

    ListModel {
        id: someModel
        ListElement {lat: 0; lon: 0}
        ListElement {lat: 5; lon: 0}
        ListElement {lat: 5; lon: 5}
        ListElement {lat: 0; lon: 5}
    }

    Timer {
        interval: 1000
        running: true
        repeat: true
        property bool toggle: true
        onTriggered: {
            if (toggle)
                someModel.append({lat: 2.5, lon: 2.5});
            else
                someModel.remove(4);
            toggle = !toggle;
        }
    }

    Map {
        id: map
        anchors.fill: parent
        plugin: Plugin {name: "osm"}
        center: QtPositioning.coordinate(2.5, 2.5)
        zoomLevel: 6

        Instantiator {
            model: someModel
            delegate: MapItemGroup {
                id: delegateGroup
                MapCircle {
                    id: innerCircle
                    border.color: "green"
                    border.width: 3
                    center: QtPositioning.coordinate(model.lat, model.lon)
                    radius: 75*1000
                }

                MapRectangle {
                    id: innerRect
                    border.color: "red"
                    border.width: 6
                    topLeft     : QtPositioning.coordinate(model.lat+2, model.lon-2)
                    bottomRight : QtPositioning.coordinate(model.lat-2, model.lon+2)
                }
            }
            onObjectAdded: map.addMapItemGroup(object)
            onObjectRemoved: map.removeMapItemGroup(object)
        }
    }
}

那是 fixed in Qt 5.12,所以您可以像现在一样使用您的代码

import QtLocation 5.12
import QtPositioning 5.12