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

时间:2018-03-27 13:10:42

标签: qt delegates qml model-view

情况:我可以将QML Map项目与Model / View / delegate一起使用。我能够处理个别物品。

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

我的方法:

  1. 我认为使用 MapItemGroup 会有效。但似乎我错过了一些东西。关于如何使其作为委托组件工作,文档也没有那么广泛。附加的代码段显示了此实现。

    Qt's Documentation on MapItemGroup

  2. 在下面的代码中:

    • delegateCircle,delegateRect正常工作
    • 不显示delegateGroup

    一个简单的实现:

    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)
                    }
                }
            }
        }
    }
    

    上述代码的输出是: The output of the QML code

    1. 我还尝试将 MapItemGroup 用作 MapQuickItem 类型的 sourceItem 。这也不起作用。
    2. 我想要实现的目标:

      好。我需要使用 MapItemView 绘制多个地图项。欢迎使用任何其他解决方案/方法(包括c ++后端程序)。

      修改

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

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

3 个答案:

答案 0 :(得分:2)

不幸的是,MapItemView仅适用于MapItem - 派生商品,MapItemGroup不是其中之一。

您可以使用Repeater,它适用于从头开始创建的代理,但如果稍后在模型中添加行,它将无效。 我在this other answer中解释了为什么Repeater不适合Map

在我的回答中,我建议使用MapItemView,但这不适用于此。 希望还有最后一个解决方案:
Instantiator Map.addMapItemGroup()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)
        }
    }
}

答案 1 :(得分:2)

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

data = pd.DataFrame("School":{1,2,3,1,2,2}, "Age":{NaN, NaN, 20, NaN, NaN, 15})

答案 2 :(得分:1)

您可以使用简单的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必须是"手动"添加到地图中,因此行Component.onCompleted: map.addMapItemGroup(this)