GeoJson-Betrachter (QML)
Das GeoJson-Viewer-Beispiel demonstriert, wie MapItems manipuliert, Benutzereingaben verarbeitet und I/O von und zu einer GeoJson-Datei durchgeführt werden.
Das Beispiel zeigt eine Karte mit verschiedenen MapItems an. Die MapItems werden entweder aus einer GeoJson-Datei importiert, indem die GeoJsonData API von QtLocation verwendet wird, oder vom Benutzer mit TapHandlers gezeichnet.
Beispiele für GeoJson-Dateien finden Sie im Verzeichnis data im Beispielverzeichnis.
Um ein MapItem zu zeichnen, klicken Sie mit der rechten Maustaste auf einen leeren Teil der Karte und wählen Sie im erscheinenden Menü einen Elementtyp Ihrer Wahl aus. Mit den nächsten Klicks wird das gewählte Element definiert. Im Beispiel können Sie MapCircles, MapRectangles, MapPolygons und MapPolylines zeichnen. Elemente, die vollständig durch zwei Punkte definiert sind, d. h. Kreise und Rechtecke, werden mit zwei Klicks der linken Maustaste gezeichnet. Elemente, die durch mehrere Punkte definiert sind, d. h. Polygone und Polylinien, werden durch eine beliebige Anzahl von Klicks mit der linken Maustaste erstellt und mit der rechten Maustaste abgeschlossen. Auf diese Weise gezeichnete Elemente werden als Punkte, Polygone und Polylinien gespeichert, um der GeoJson-Spezifikation zu entsprechen, siehe https://geojson.org/.
Ausführen des Beispiels
Zum Ausführen des Beispiels von Qt Creatorzu starten, öffnen Sie den Modus Welcome und wählen Sie das Beispiel aus Examples. Weitere Informationen finden Sie unter Erstellen und Ausführen eines Beispiels.
Erstellen einer MapView
Zunächst erstellen wir eine Basiskarte, auf der alle Elemente platziert werden können. Wir nutzen ein MapView -Element, das eine grundlegende Map mit der Verarbeitung von Eingaben (Mausrad, Ziehen, etc.) kombiniert. Auf die zugrunde liegende Map kann mit der Eigenschaft map zugegriffen werden. Wenn Sie eine Eigenschaft in MapView vermissen, können Sie höchstwahrscheinlich mit MapView.map darauf zugreifen.
MapView { id: view anchors.fill: parent map.plugin: Plugin { name: "osm" } map.zoomLevel: 4 map.center: QtPositioning.coordinate(3, 8) }
Einrichten des GeoJson-Modells / Anzeige von MapItems
Um die Dateiinhalte auf der Karte anzuzeigen, werden wir ein Design Pattern verwenden, das als Model/View Programming bekannt ist. Zunächst müssen wir eine geeignete Ansicht einrichten, in diesem Beispiel ein MapItemView Element. Sein Parent muss auf die zugrunde liegende Map von MapView gesetzt werden, damit alle darin platzierten Elemente korrekt angezeigt werden.
MapItemView { id: miv parent: view.map }
Als nächstes benötigen wir ein geeignetes Modell, das ein GeoJSON-Dokument darstellt. Zu diesem Zweck bietet QtLocation das Element GeoJsonData, das GeoJSON-Dateien lesen und schreiben kann. Es kann einfach instanziiert werden
GeoJsonData { id: geoDatabase sourceUrl: ":/data/11-full.json" }
und dem MapItemView zugewiesen werden.
model: geoDatabase.model
Als Beispiel wird die Datei 11-full.json
beim Start geladen.
Schließlich benötigen wir ein delegate, das die Modelldaten in eine Darstellung von Elementen übersetzt und das MapItemView füllt.
delegate: GeoJsonDelegate {}
Das Element GeoJsonDelegate
wird in der Datei GeoJsonDelegate.qml
deklariert. Es ist ein DelegateChooser Element, um die unterschiedlichen Eigenschaften der verschiedenen Geometrietypen zu berücksichtigen.
DelegateChooser { id: dc role: "type" }
Die Datei DelegateChooser enthält ein DelegateChoice für jeden Geometrietyp, der in einer GeoJson-Datei gefunden werden kann. Die Eigenschaft role wird mit DelegateChoice.roleValue abgeglichen, um den richtigen Delegaten zu bestimmen.
So wird beispielsweise ein Punkt, der in GeoJson mit "type":"Point"
beschrieben wird, durch MapCircle auf MapItemView dargestellt:
DelegateChoice { roleValue: "Point" delegate: MapCircle { property string geojsonType: "Point" property var props: modelData.properties geoShape: modelData.data radius: (props && props.radius) || 20*1000 border.width: 2 border.color: hh.hovered ? "magenta" : Qt.darker(color) opacity: dc.defaultOpacity color: (props && props.color) || (parent && parent.props && parent.props.color) || dc.defaultColor } }
Eigenschaften der MapCircle, wie color oder radius werden versucht, aus der GeoJson-Datei zu lesen, die in Form der modelData-Eigenschaft verfügbar ist. Dies ist jedoch kein strenger Standard von GeoJson und es werden für alle Eigenschaften Fallback-Werte gesetzt.
Schreiben von MapItems in GeoJson
Um MapItems in eine GeoJson-Datei zu schreiben, können wir einfach die Funktion GeoJsonData::saveAs mit dem angegebenen Dateinamen aufrufen. Dadurch werden alle Elemente des aktuellen Modells in die angegebene Datei geschrieben. Alle anderen Elemente, die in die Datei geschrieben werden sollen, müssen zuerst mit der Funktion GeoJsonData::addItem oder GeoJsonData::setModelToMapContents zum Modell hinzugefügt werden.
geoDatabase.saveAs(fileWriteDialog.selectedFile)
Benutzerinteraktion mit MapItems
Für die Benutzerinteraktion werden wir PointHandlers verwenden. Sie sind für diese Aufgabe besonders gut geeignet, da sie sich genau an die Form des zugrundeliegenden Elements anpassen, im Gegensatz zu MouseArea, das immer eine quadratische Form abdeckt. MapItems, die aus einer GeoJson-Datei importiert werden, erhalten ihre eigenen HoverHandler und TapHandler direkt im Delegaten:
TapHandler { onTapped: { if (props !== undefined) console.log(props.name) else if (parent.parent.geojsonType == "MultiPoint") console.log(parent.parent.props.name) else console.log("NO NAME!", props) } } HoverHandler { id: hh }
Die TapHandler wird verwendet, um einige Informationen über das Element auf die Konsole zu schreiben, wenn das Element angetippt wird. Die HoverHandler wird verwendet, um Elemente hervorzuheben, die sich unter dem Mauszeiger befinden. Dies wird durch die Beschreibung der Eigenschaft border.color in Abhängigkeit von der Eigenschaft / dem Zustand hovered des HoverHandler realisiert.
Hinzufügen neuer Elemente
Eine Kombination aus HoverHandler und TapHandler für die MapView ermöglicht es uns, auf Mausbewegungen und -klicks des Benutzers zu reagieren.
Wenn die TapHandler ein Signal singleTapped sendet, wird ein neues MapItem auf LeftButton erstellt oder geändert und das MapItem auf RightButton beendet. Wenn es kein Element zu beenden gibt, dann wird RightButton ein Menü öffnen.
onSingleTapped: (eventPoint, button) => { lastCoordinate = view.map.toCoordinate(tapHandler.point.position) if (button === Qt.RightButton) { if (view.unfinishedItem !== undefined) { view.finishGeoItem() } else mapPopupMenu.show(lastCoordinate) } else if (button === Qt.LeftButton) { if (view.unfinishedItem !== undefined) { if (view.unfinishedItem.addGeometry(view.map.toCoordinate(tapHandler.point.position), false)) { view.finishGeoItem() } } } }
Das Signal pointChanged wird verwendet, um ein MapItem vorübergehend zu aktualisieren und dem Benutzer eine Vorschau zu geben.
HoverHandler { id: hoverHandler property variant currentCoordinate grabPermissions: PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType onPointChanged: { currentCoordinate = view.map.toCoordinate(hoverHandler.point.position) if (view.unfinishedItem !== undefined) view.unfinishedItem.addGeometry(view.map.toCoordinate(hoverHandler.point.position), true) } }
Mapitems werden aus Prototypen erzeugt, die in separaten qml-Dateien definiert sind. Sie werden mit der Funktion createComponent erstellt und mit addMapItem in die Karte eingefügt. Ein Verweis auf das neue Element wird zur weiteren Bearbeitung durch den Benutzer gespeichert.
function addGeoItem(item) { var co = Qt.createComponent('mapitems/'+item+'.qml') if (co.status === Component.Ready) { unfinishedItem = co.createObject(map) unfinishedItem.setGeometry(tapHandler.lastCoordinate) unfinishedItem.addGeometry(hoverHandler.currentCoordinate, false) view.map.addMapItem(unfinishedItem) } else { console.log(item + " is not supported right now, please call us later.") } }
Das Hinzufügen des Elements zu Map reicht aus, um das Element anzuzeigen. Um das Element jedoch weiter zu verwenden (z. B. in einer Datei zu speichern), muss es zum Modell hinzugefügt werden. Dies geschieht, nachdem die Bearbeitung abgeschlossen ist:
function finishGeoItem() { unfinishedItem.finishAddGeometry() geoDatabase.addItem(unfinishedItem) map.removeMapItem(unfinishedItem) unfinishedItem = undefined }
Entfernen von Objekten
Um alle Elemente aus der Karte zu entfernen, rufen wir einfach die Reset-Funktion des GeoJsonData -Objekts auf
function clearAllItems() { geoDatabase.clear(); }
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.