viernes, 26 de julio de 2013

Creando un componente simple de QML para usar en mapas. Un ejemplo con QT Location en QT 5


Ayer andaba buscando iconos para usar en una aplicación con mapas y me encontré con un recurso bastante interesante llamado Map Icons Designer. Como podréis ver tienen una pinta bastante atractiva y, si seguís viendo su página, encontraréis que por un lado se nos proporcionan los pines y por otro los símbolos.  La solución, evidentemente, es juntar ambas cosas con algo de coherencia y en el caso que se muestra a continuación se hará mediante un componente QML creado a partir de dos imágenes.

Primero un componente QML facilón

La cosa es bastante fácil, sólo hay que posicionar el símbolo sobre el marcador y para ello usaremos la propiedad "anchor": la posición relativa de ambos tendrá el mismo centro horizontal, después alinearemos el borde superior del símbolo al pin pero dándole un margen adecuado.

anchors.top: parent.top
anchors.topMargin: 10
anchors.horizontalCenter: parent.horizontalCenter

Por otro lado, aunque vamos a usar sólo uno de los marcadores que se nos proporcionan, los iconos a situar en el interior los deberemos elegir dinámicamente. Esto lo conseguiremos creando una propiedad, usando "property alias", en la que indicaremos el elemento que queremos.

property alias symbol:symbol.source

Además podemos meter todas las imágenes en un archivo .qrc y darles una alias para facilitar el acceso desde la aplicación. En la captura que hay a continuación se puede ver que hay definidos dos prefijos uno para los pines y otro para los símbolos.


De momento, el componente queda tal y como se muestra aquí:

import QtQuick 2.0

Image {
    property alias symbol:symbol.source
    id: pin
    source: "qrc:/pins/blue"
    Image{
        id: symbol
        anchors.top: parent.top
        anchors.topMargin: 10
        anchors.horizontalCenter: parent.horizontalCenter
    }
} 

Un ejemplo con QT Location

En cuanto a su utilización, para obtener algo similar a la imagen que se encuentra más abajo, puede incluirse dentro en un Map del módulo QT Location, pintándolo a traves de un MapQuickItem:

   
Map {
        id: nmap
        center {
            latitude: -27
            longitude: 153
        }

        zoomLevel: 10
        plugin : Plugin {name : "osm"} 
        MapQuickItem {
            coordinate: nmap.center
            anchorPoint: "0,0"
            sourceItem: Marker{symbol:"qrc:/symbols/car"}
        }
} 
Pero esto nos llevará a pensar que, puestos a usarlo con qtLocation, será mejor si el propio componente es un MapQuickItem, con lo que heredará todas sus propiedades. Además, añadiremos un par de cosas: 
  • Por un lado corregiremos el posicionamiento del elemento. En QML nuestros elementos se posicionan tomando como referencia el vértice superior izquierdo y, como se puede ver, el pin tiene una punta abajo y centrada para indicar el punto exacto en el que se localiza. Esto lo solucionamos indicando lo siguiente:
  
    anchorPoint.x: pin.width/2
    anchorPoint.y: pin.height
  • Además añadiremos un  MouseArea para detectar eventos sobre el marcador. En el ejemplo solo se trata el click pero podrían ponerse más
Por tanto, el componente nos queda así:
  
import QtQuick 2.0
import QtLocation 5.0

MapQuickItem{
    id: root
    property alias symbol:symbol.source
    signal clicked()

    anchorPoint.x: pin.width/2
    anchorPoint.y: pin.height

    sourceItem: Image {
        id: pin
        source: "qrc:/pins/blue"
        Image{
            id: symbol
            anchors.top: parent.top
            anchors.topMargin: 10
            anchors.horizontalCenter: parent.horizontalCenter
        }
    }
    MouseArea{
        anchors.fill:parent
        onClicked: root.clicked()
    }
}
Y podremos usarlo de la siguiente manera::
  
import QtQuick 2.0
import QtLocation 5.0

Rectangle{
    width: 480;
    height: 300;

    Map {
        id: nmap
        width: parent.width
        height: parent.height
        anchors.centerIn: parent

        center {latitude: -27;longitude: 153}
        zoomLevel: 10

        gesture.flickDeceleration: 3000
        gesture.enabled: true
        plugin : Plugin { name : "osm"}

        Marker {
            symbol:"qrc:/symbols/car"
            coordinate{
                latitude:-27
                longitude:153
            }
            onClicked: console.log("clicked!")
        }

        Marker {
            symbol:"qrc:/symbols/food"
            coordinate{
                latitude:-27.1
                longitude:153.1
            }
        }
    }
}

El proyecto en GitHub 

 Para terminar sólo queda decir que el proyecto está disponible en GitHub, lo tenéis aquí. Se debe tener en cuenta que hay que descargar a parte los iconos, el autor no permite la redistribución, y que se trata de un proyecto en QT5 por tanto hay  que compilar QT Location por nuestra cuenta, ya que es un módulo externo.
Publicar un comentario