Logo von Developer

Suche
Abonnieren

Tägliche Top-News bei WhatsApp, Facebook Messenger, Telegram & Insta

preisvergleich_weiss

Recherche in 1.733.931 Produkten

Tam Hanna 1

Mapping, Geocoding und Routing mit Qt Location

Die schon länger in Entwicklung befindliche Qt-Location-Erweiterung sieht sich selbst als Abstraktionsschicht zwischen Kartenrenderer, Routinganbieter und Entwickler. Mit Qt 5.5 im letzten Jahr hat das Paket – endlich – Preview-Status erreicht.

Geodäsie ist ein komplexes Thema: Mit dem Sammeln und Auswerten von Geodaten lässt sich viel Geld verdienen. Es ist somit nicht verwunderlich, dass eine Vielzahl von Unternehmen und Projekten nach ihrem Teil des Kuchens greift. Für Entwickler ist diese Diversität nur in den wenigsten Fällen hilfreich. Die Anbieter achten penibel darauf, ihre APIs so proprietär wie möglich aufzubauen, weswegen oft umfangreiche Codeänderungen erforderlich sind.

Qt Location begann als API für Nokias hauseigene Kartendienste: Die Finnen wollten ihren Entwicklern das Hantieren mit nativen APIs für Symbian, MeeGo und Meltemi ersparen. Nach dem Verkauf von Qt an Digia war ein neuer Kartenprovider zu finden.

Anzeige

Anstatt sich abermals auf ein bestimmtes Unternehmen festzulegen, entschied man sich stattdessen für die Einführung einer Abstraktionsschicht. Wer auf Qt Location setzt, ist vom Kartendienstanbieter unabhängig: Neben OpenStreetMap gibt es auch Plug-ins für kommerzielle Datenquellen.

Wer Qt 5.5 mit dem Online-Installer auf seine Workstation holt, kann die Mitauslieferung von Qt Location über den in der Abbildung gezeigten Dialog anweisen.

Der Download von Qt Location setzt eine explizite Aufforderung voraus (Abb. 1).

Im nächsten Schritt müssen Entwickler eine neue QtQuick-Applikation erstellen und die .pro-Datei zwecks Einbindung von Qt Location folgendermaßen adaptieren. (C++-Entwickler müssen an der Stelle "draußen bleiben", da die Mapping-Steuerelemente derzeit nur in Form von QML-Komponenten angeboten werden):

QT += location

MainForm.ui.qml wird im nächsten Schritt im Editormodus geöffnet und zwecks Integration eines Maps-Steuerelements folgendermaßen angepasst:

Update

Der Artikel beruht auf Qt 5.5. aktuell ist jedoch die Version 5.6, die den besprochenen Bug mit der MouseArea behebt. Zudem wurde die Kompatibilität der Module erhöht: Qt Location steht nun auf allen unterstützten Plattformen zur Verfügung, während Qt Positioning unter Android, iOS, OS X, Linux und WinRT einsetzbar ist. Mit QML arbeitende Entwickler dürfen sich zudem an einem erweiterten Qt-Location-Modul erfreuen, das die Navigations- und POI-APIs aus QML heraus ansprechbar mach.

import QtQuick 2.5
import QtPositioning 5.5
import QtLocation 5.5

Nach dem Import der notwendigen Namespaces müssen Entwickler eine Instanz der Plugin-Klasse errichten. Es handelt sich dabei um ein Abstraktionsobjekt, das als Makler zwischen der MapView und der zu verwendenden Datenquelle dient:

Anzeige
Rectangle {
width: 640
height: 480
Plugin {
id: mDataSource
name: "osm"
}

Im Fall von OpenStreetMap ist die Situation insofern angenehm, als das Plug-in – bis auf den für die Identifikation der Kartenart notwendigen Name-String – keine weiteren Eigenschaften voraussetzt. Andere Plug-ins zeigen sich hier weniger kooperativ. Das Here-Plug-in ist besonders anspruchsvoll – seine Initialisierung setzt das Vorhandensein einer App-ID und eines Tokens voraus:

Plugin {
name: "here"
PluginParameter { name: "here.app_id"; value: "<NAME>" }
PluginParameter { name: "here.token"; value: "<TOKEN>" }
}

Damit kann man sich der Realisierung der Map zuwenden, die im Fall des vorliegenden Beispiels so aussieht:

    Map {
id: map
width: 600
height: 400
plugin: mDataSource
center {
latitude: -27
longitude: 153
}
zoomLevel: map.minimumZoomLevel
gesture.enabled: true
}
}

Nach dem Öffnen der main.qml setzen Entwickler den für die hier nicht mehr benötigte MouseArea vorgesehenen Eventhandler. width und height bekommen sinnvolle Werte, um dem Nutzer das manuelle Anpassen der Fenstergröße zu ersparen:

Window {
visible: true
width: 640
height: 480
MainForm {
anchors.fill: parent
}
}

Ab diesem Zeitpunkt lässt sich das Programm ausführen: Bei funktionierender Internetverbindung ist die Karte per Drag & Drop bewegbar. Leider bleiben fortgeschrittene Gesten noch ohne Wirkung: Es ist nicht möglich, den gerade aktuellen Kartenausschnitt zu zoomen. Die Integration eines Gestenlisteners ist keine wirksame Maßnahme – aufgrund eines derzeit noch nicht behobenen Fehlers ist eine MouseArea einzupflegen. Bei der Gelegenheit lässt sich auch gleich ein vollwertiges Zoomsystem implementieren. Die Arbeit beginnt mit folgender Anpassung:

Map {
id: map
. . .
MouseArea {
id: mouseArea
property variant lastCoordinate
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onDoubleClicked: {
map.center = map.toCoordinate(Qt.point(mouse.x, mouse.y))
if (mouse.button === Qt.LeftButton) {
map.zoomLevel++
} else if (mouse.button === Qt.RightButton) {
map.zoomLevel--
}
}
}
}

Da die Erkennung von Doppel-Taps derzeit eher schlecht als recht funktioniert, bekommt die Map per MouseArea einen eigenen Klickdetektor. Beim Erkennen eines Doppelklicks – die MouseArea zeigt das per Aufruf von onDoubleClicked an – wird im ersten Schritt ausgewertet, welche Maustaste genutzt wurde. Durch Doppellinksklick erhöht man die als Integer vorliegende Zoomstufe um 1, während ein Rechtsklick eine Senkung um 1 bewirkt.

Vor dem Anpassen der Zoomstufe ist der angeklickte Kartenausschnitt noch in die Mitte des Bildschirms zu bringen. Dazu nutzt man map.toCoordinate, um die von der MouseArea angelieferten Bildschirmkoordinaten in geodätische Koordinaten umzuwandeln. Abbildung 2 zeigt einen Kartenausschnitt in "Nah-Ansicht".

OpenStreetMap liefert beeindruckend genaue Daten (Abb. 2).

1 Kommentar

Themen:

Anzeige
Anzeige