Localizador de planos (QML)
El ejemplo Plane Spotter demuestra la estrecha integración de los tipos de datos de localización y posicionamiento en QML.

El ejemplo Plane Spotter demuestra cómo integrar en QML tipos de datos de C++ relacionados con la localización y el posicionamiento y viceversa. Esto resulta útil cuando se desea ejecutar cálculos de posición intensivos en CPU en entornos nativos, pero los resultados deben mostrarse utilizando QML.
El ejemplo muestra un mapa de Europa y aviones en dos rutas a través de Europa. El primer avión se desplaza entre Oslo y Berlín y el segundo entre Londres y Berlín. El seguimiento de la posición de cada avión se implementa en C++. El avión Oslo-Berlín está pilotado en QML y el avión Londres-Berlín está comandado por un piloto en C++.
Ejecución del ejemplo
Para ejecutar el ejemplo desde Qt Creator, abra el modo Welcome y seleccione el ejemplo de Examples. Para más información, consulte Qt Creator: Tutorial: Construir y ejecutar.
Visión general
Este ejemplo hace uso de la característica Q_GADGET como parte de su implementación del controlador de posición. Permite la integración directa de tipos de valores C++ no basados enQObject en QML.
El propósito principal de la clase PlaneController es rastrear las coordenadas actuales del plano en un momento dado. Expone la posición a través de su propiedad position.
class PlaneController: public QObject { Q_OBJECT Q_PROPERTY(QGeoCoordinate position READ position WRITE setPosition NOTIFY positionChanged) // ... };
La función main() del ejemplo se encarga de vincular las instancias de la clase PlaneController al contexto QML:
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(); }
Al igual que las clases derivadas de QObject, QGeoCoordinate puede integrarse sin una envoltura QML adicional.
Dirigir los planos
Como se ha mencionado anteriormente, el objetivo principal de la clase PlaneController es realizar un seguimiento de las posiciones actuales de los dos aviones (Oslo-Berlín y Londres-Berlín) y anunciarlas como una propiedad a la capa QML. Su propósito secundario es establecer y hacer progresar un avión a lo largo de una ruta de vuelo determinada. En cierto sentido, puede actuar como piloto. Es muy parecido a CoordinateAnimation, que puede animar la transición de una coordenada geográfica a otra. Este ejemplo muestra cómo se modifica la propiedad de posición de PlaneController mediante código C++ utilizando las propias capacidades de pilotaje de PlaneController y mediante código QML utilizando CoordinateAnimation como piloto. El avión Oslo-Berlín se anima utilizando código QML y el avión Londres-Berlín se anima utilizando código C++.
Independientemente del piloto que se utilice, los resultados de las acciones del piloto son visibles en C++ y QML, por lo que el ejemplo demuestra el intercambio directo y sin obstáculos de datos de posición a través de la frontera entre C++ y QML.
La representación visual de cada Plane se realiza utilizando el tipo MapQuickItem que permite la incrustación de elementos QtQuick arbitrarios en un mapa:
// Plane.qml MapQuickItem { id: plane property string pilotName; property int bearing: 0; anchorPoint.x: image.width/2 anchorPoint.y: image.height/2 sourceItem: Item { //... } }
El piloto C
El plano C++ está dirigido por C++. Las propiedades from y to de la clase controlador establecen el origen y el destino que el piloto utiliza para calcular el rumbo del avión:
Q_PROPERTY(QGeoCoordinate from READ from WRITE setFrom NOTIFY fromChanged) Q_PROPERTY(QGeoCoordinate to READ to WRITE setTo NOTIFY toChanged)
El piloto emplea QBasicTimer y QTimerEvents para actualizar constantemente la posición. Durante cada iteración del temporizador se llama a PlaneController::updatePosition() y se calcula una nueva posición.
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(); }
Una vez calculada la nueva posición, se llama a setPosition() y la notificación de cambio subsiguiente de la propiedad empuja la nueva posición a la capa QML.
El plano C++ se inicia haciendo clic en el plano:
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() calcula el rumbo en grados de una coordenada a otra. Observe que el código anterior utiliza una animación QML para unir la rotación y el cambio de posición en un único flujo de animación:
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() } }
Primero, NumberAnimation rota el plano en la dirección correcta y una vez hecho esto la función startFlight() se encarga de iniciar el cambio de posición del plano.
public slots: void startFlight() { if (timer.isActive()) return; startTime = QTime::currentTime(); finishTime = startTime.addMSecs(ANIMATION_DURATION); timer.start(15, this); emit departed(); }
El piloto QML
El tipo CoordinateAnimation se utiliza para controlar el vuelo de Oslo a Berlín y viceversa. Sustituye al anterior ScriptAction.
CoordinateAnimation { id: coordinateAnimation; duration: 5000 target: oslo2Berlin; property: "position" easing.type: Easing.InOutQuad }
El TapHandler del avión QML implementa la lógica para el ajuste del rumbo e inicia la animación cuando es necesario.
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() } }
© 2026 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.