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.
Qt's Documentation on MapItemGroup
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)
}
}
}
That was fixed in Qt 5.12, so You may use Your code as is now with
import QtLocation 5.12
import QtPositioning 5.12
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With