Flugzeug-Spotter (QML)
Das Beispiel Plane Spotter
demonstriert die enge Integration von orts- und positionsbezogenen Datentypen in QML.
Das Beispiel Plane Spotter
zeigt, wie man orts- und positionsbezogene C++-Datentypen in QML integriert und umgekehrt. Dies ist nützlich, wenn es wünschenswert ist, CPU-intensive Positionsberechnungen in nativen Umgebungen durchzuführen, die Ergebnisse aber mit QML angezeigt werden sollen.
Das Beispiel zeigt eine Europakarte und Flugzeuge auf zwei Routen durch Europa. Das erste Flugzeug pendelt zwischen Oslo und Berlin und das zweite Flugzeug pendelt zwischen London und Berlin. Die Positionsverfolgung jedes Flugzeugs ist in C++ implementiert. Das Flugzeug Oslo-Berlin wird in QML gesteuert und das Flugzeug London-Berlin wird von einem C++-Piloten kommandiert.
Ausführen des Beispiels
Zum Ausführen des Beispiels von Qt Creatorzu starten, öffnen Sie den Modus Welcome und wählen Sie das Beispiel unter Examples aus. Weitere Informationen finden Sie unter Erstellen und Ausführen eines Beispiels.
Überblick
Dieses Beispiel nutzt die Funktion Q_GADGET als Teil der Implementierung des Positionsreglers. Es ermöglicht die direkte Integration von nicht aufQObject basierenden C++-Wertetypen in QML.
Der Hauptzweck der Klasse PlaneController
besteht darin, die aktuellen Koordinaten der Ebene zu einem bestimmten Zeitpunkt zu verfolgen. Sie gibt die Position über ihre Eigenschaft position bekannt.
class PlaneController: public QObject { Q_OBJECT Q_PROPERTY(QGeoCoordinate position READ position WRITE setPosition NOTIFY positionChanged) // ... };
Die Funktion main()
des Beispiels ist für die Einbindung der Instanzen der Klasse PlaneController
in den QML-Kontext verantwortlich:
int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); PlaneController oslo2berlin; PlaneController berlin2london; QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("oslo2Berlin", &oslo2berlin); engine.rootContext()->setContextProperty("berlin2London", &berlin2london); engine.load(QUrl(QStringLiteral("qrc:/planespotter.qml"))); return app.exec(); }
Ähnlich wie die von QObject abgeleiteten Klassen kann QGeoCoordinate ohne einen zusätzlichen QML-Wrapper integriert werden.
Die Steuerung der Flugzeuge
Wie bereits erwähnt, besteht der primäre Zweck der Klasse PlaneController
darin, die aktuellen Positionen der beiden Flugzeuge (Oslo-Berlin und London-Berlin) zu verfolgen und sie der QML-Schicht als Eigenschaft mitzuteilen. Ihr sekundärer Zweck besteht darin, ein Flugzeug entlang einer bestimmten Flugroute zu positionieren und zu bewegen. In gewisser Weise kann sie als Pilot fungieren. Dies ist sehr ähnlich wie CoordinateAnimation, das den Übergang von einer Geokoordinate zu einer anderen animieren kann. Dieses Beispiel zeigt, wie die Positionseigenschaft von PlaneController
durch C++-Code unter Verwendung der eigenen Pilotenfähigkeiten des PlaneControllers und durch QML-Code unter Verwendung von CoordinateAnimation als Pilot geändert wird. Das Flugzeug Oslo-Berlin wird mit QML-Code animiert und das Flugzeug London-Berlin mit C++-Code.
Unabhängig davon, welcher Pilot verwendet wird, sind die Ergebnisse der Aktionen des Piloten in C++ und QML sichtbar, und somit demonstriert das Beispiel den ungehinderten und direkten Austausch von Positionsdaten über die C++/QML-Grenze.
Die visuelle Darstellung der einzelnen Plane
erfolgt über den Typ MapQuickItem, der die Einbettung beliebiger QtQuick Elemente in eine Karte erlaubt:
// Plane.qml MapQuickItem { id: plane property string pilotName; property int bearing: 0; anchorPoint.x: image.width/2 anchorPoint.y: image.height/2 sourceItem: Item { //... } }
Der C++-Pilot
Die C++-Ebene wird von C++ gesteuert. Die Eigenschaften from
und to
der Controllerklasse legen den Ursprung und das Ziel fest, die der Pilot zur Berechnung der Richtung des Flugzeugs verwendet:
Q_PROPERTY(QGeoCoordinate from READ from WRITE setFrom NOTIFY fromChanged) Q_PROPERTY(QGeoCoordinate to READ to WRITE setTo NOTIFY toChanged)
Der Pilot verwendet QBasicTimer und QTimerEvents, um die Position ständig zu aktualisieren. Während jeder Iteration des Zeitgebers wird PlaneController::updatePosition()
aufgerufen und eine neue Position berechnet.
void updatePosition() { // simple progress animation qreal progress; QTime current = QTime::currentTime(); if (current >= finishTime) { progress = 1.0; timer.stop(); } else { progress = ((qreal)startTime.msecsTo(current) / ANIMATION_DURATION); } setPosition(coordinateInterpolation( fromCoordinate, toCoordinate, easingCurve.valueForProgress(progress))); if (!timer.isActive()) emit arrived(); }
Sobald die neue Position berechnet ist, wird setPosition()
aufgerufen und die anschließende Änderungsbenachrichtigung der Eigenschaft schiebt die neue Position in die QML-Ebene.
Die C++-Ebene wird durch Klicken auf die Ebene gestartet:
Plane { id: cppPlane pilotName: "C++" coordinate: berlin2London.position TapHandler { onTapped: { if (cppPlaneAnimation.running || berlin2London.isFlying()) { console.log("Plane still in the air."); return; } berlin2London.swapDestinations(); cppPlaneAnimation.rotationDirection = berlin2London.position.azimuthTo(berlin2London.to) cppPlaneAnimation.start(); cppPlane.departed(); } } }
azimuthTo() berechnet die Peilung in Grad von einer Koordinate zur anderen. Beachten Sie, dass der obige Code eine QML-Animation verwendet, um die Drehung und die Positionsänderung in einen einzigen Animationsablauf einzubinden:
SequentialAnimation { id: cppPlaneAnimation property real rotationDirection : 0; NumberAnimation { target: cppPlane; property: "bearing"; duration: 1000 easing.type: Easing.InOutQuad to: cppPlaneAnimation.rotationDirection } ScriptAction { script: berlin2London.startFlight() } }
Zuerst dreht NumberAnimation die Ebene in die richtige Richtung, und sobald dies geschehen ist, sorgt die Funktion startFlight()
für den Start der Positionsänderung der Ebene.
public slots: void startFlight() { if (timer.isActive()) return; startTime = QTime::currentTime(); finishTime = startTime.addMSecs(ANIMATION_DURATION); timer.start(15, this); emit departed(); }
Der QML-Pilot
Der Typ CoordinateAnimation wird verwendet, um den Flug von Oslo nach Berlin und umgekehrt zu steuern. Er ersetzt den obigen ScriptAction.
CoordinateAnimation { id: coordinateAnimation; duration: 5000 target: oslo2Berlin; property: "position" easing.type: Easing.InOutQuad }
Die TapHandler des QML-Flugzeugs implementiert die Logik für die Kursbestimmung und startet bei Bedarf die Animation.
TapHandler { onTapped: { if (qmlPlaneAnimation.running) { console.log("Plane still in the air."); return; } if (oslo2Berlin.position === berlin) { coordinateAnimation.from = berlin; coordinateAnimation.to = oslo; } else if (oslo2Berlin.position === oslo) { coordinateAnimation.from = oslo; coordinateAnimation.to = berlin; } qmlPlaneAnimation.rotationDirection = oslo2Berlin.position.azimuthTo(coordinateAnimation.to) qmlPlaneAnimation.start() } }
© 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.