Situation: I am able to use QML Map item with Model/View/delegate. I am able to work with individual items.
Problem: As a next step, I would like to be able to draw multiple items. I need to put multiple QML MapItems (like MapCircle, MapRectangle, etc..) in a single delegate component. In general, QML supports multiple items within a delegate. The problem is with MapItemView's delegate: it does not support multiple children items.
My Approach:
I thought using MapItemGroup would work. But it seems like I am missing something. The documentation is also not so extensive on how I can make it work as a delegate component. The attached snippet shows this implementation.
In the code below:
A simple implementation:
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 above code is:
What I want to achieve:
Well. I need to draw multiple map items using a MapItemView. Any other solution/method (including c++ backend program) is welcome.
EDIT
Thank you @GrecKo and @Yoann. Both of your solutions work. However, I chose to continue with Instantiator since it is more suited for my application.
I also found this interesting after seeing your solution: a developer's discussion on populating a model using Repeater and Instantiator.
Unfortunately, MapItemView
only works with MapItem
-derived items, and MapItemGroup
is not one of them.
You could use a Repeater
and it will work for delegates created from the start, but it won't work if you add rows in your model later on.
I explained in this other answer why Repeater
is not well suited for a Map
.
In my answer I advise to use MapItemView
but it's not applicable here.
Hopefully, there is still one last available solution :
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)
}
}
}