Desarrollando mi primera aplicación para Ubuntu Phone OS (II)

Introducción

Superado la primera parte, “Desarrollando mi primera aplicación para Ubuntu Phone OS (I)“, que se centraba básicamente en la instalación de las herramientas necesarias para el desarrollo de aplicaciones para Ubuntu Phone OS y en el diseño del primer interfaz; en este segundo artículo, quiero centrarme en explicar con detalle los diferentes objetos que constituyen el diseño del artículo anterior, y algunas características propias de los componentes del SDK de Ubuntu.

Desgranando la aplicación

El primer paso va a ser ir “desgranando” la interfaz gráfica que hicimos el otro día. Para ello, voy a revisar los diferentes objetos que van apareciendo y a describir someramente cada uno de ellos. Empezamos por las primeras líneas de código:


Rectangle {
    id: root
    width: units.gu(60)
    height: units.gu(30)
    /*color: "lightgray"*/

    property real margins: units.gu(2)
    property real buttonWidth: units.gu(9)

Item

Aunque no aparece en el código, empiezo por esta, porque es el objeto visual más básico de QtQuick, y del que heredan muchos de los objetos visuales. Para aquellos que no sabéis mucho de programación o que os quedasteis en aquel lejano “basic”, indicar que la herencia es una interesante cualidad de la programación orientada a objetos, que permite que los objetos derivados tengan las características del padre (además de aquellas nuevas que queramos definirles,claro)

EL objeto Item tiene diferentes propiedades que puedes consultar en Item, sin embargo, me quiero centrar en algunas que utilizaremos de forma masiva, y es interesante tener en mente.

anchors

Esta propiedad o grupo de propiedades, nos permite definir la posición del Item respecto de otros, o de su padre. Por ejemplo, definimos dos rectangulos (está feo utilizarlo sin haberlo presentado, pero es lo más gráfico), y la posición de uno de ellos la indicamos con coordenadas, y la del otro rectángulo mediente “anchors”, para indicar que “test2″ está a la derecha de “test1″ (anchors.left: test1.right), y que coinciden sus verticalmente sus centros (anchors.verticalCenter: test1.verticalCenter). Así


import QtQuick 2.0
import Ubuntu.Components 0.1

Rectangle {
    id: root
    width: units.gu(60)
    height: units.gu(30)
    /*color: "lightgray"*/

    Rectangle{
        id: test1
        x:units.gu(10)
        y:units.gu(10)
        width: units.gu(10)
        height: units.gu(10)
        color: "red"
    }
    Rectangle{
        id: test2
        width: units.gu(10)
        height: units.gu(10)
        anchors.left: test1.right
        anchors.verticalCenter: test1.verticalCenter
        color: "blue"
    }
}

Y el resultado sería algo como:

0191_Ventana sin título.png

O incluso podíamos haber centrado nuestro primer rectángulo fácilmente utilizando:


Rectangle{
        id: test1
        anchors.verticalCenter: parent.verticalCenter
        anchors.horizontalCenter: parent.horizontalCenter
        width: units.gu(10)
        height: units.gu(10)
        color: "red"
    }

Con el siguiente resultado:

0192_Ventana sin título.png

Como puedes ver la ventaja es que no tienes que definir nuevamente la posición de test2, puesto que sigue en la misma posición relativa respecto a test1. Desde luego, que esto puede no tener fin, poniendo ejemplos. Lo mas sencillo es que hagas diferentes pruebas jugando con todas las posibilidades que permite anchors, incluido anchors.leftMargin, etc y también con la posición relativa z, que te permitirá definir quien está encima de quien, de otra manera, el ultimo definido es el que estará encima de los demás:


import QtQuick 2.0
import Ubuntu.Components 0.1

Rectangle {
    id: root
    width: units.gu(60)
    height: units.gu(30)
    /*color: "lightgray"*/

    Rectangle{
        id: test1
        anchors.verticalCenter: parent.verticalCenter
        anchors.horizontalCenter: parent.horizontalCenter
        width: units.gu(10)
        height: units.gu(10)
        color: "red"
        z: 1
    }
    Rectangle{
        id: test2
        width: units.gu(10)
        height: units.gu(10)
        anchors.left: test1.right
        anchors.top: test1.top
        anchors.leftMargin: units.gu(-1)
        anchors.topMargin: units.gu(1)
        color: "blue"
    }
}

y su resultado:

0193_Ventana sin título.png

¿Que es eso de units.gu?

Esto nos permite definir unidades de medida que son (aproximadamente) independientes del equipo que se utilice, así:

  • En la mayoría de los ordenadores 1 gu = 8 px
  • Para equipos con Retina 1 gu = 16 px
  • Para teléfonos móviles 1 gu = 18 px

De esta forma nos podemos (casi) despreocupar de que aspecto tendrá nuestra aplicación en los diferentes equipos que podamos utilizar.

Rectangle

Nos permite definir un rectángulo con un color de fondo, y un borde, incluyendo el redondeado del borde y su color, e incorporando los gradientes. Así nuestro Rectangle “test1″, puede llegar a tener el siguiente aspecto:

Para ello tenemos que definirlo de la siguiente forma:


    Rectangle{
        id: test1
        anchors.verticalCenter: parent.verticalCenter
        anchors.horizontalCenter: parent.horizontalCenter
        width: units.gu(10)
        height: units.gu(10)
        z: 1
        opacity: 0.5
        rotation: 30
        antialiasing: true
        /*Las opciones de Rectangle*/
        border.color: "red"
        border.width: units.gu(1)
        radius: units.gu(3)
        gradient: Gradient {
                GradientStop { position: 0.0; color: "darkgreen" }
                GradientStop { position: 1.0; color: "lime" }
            }
    }

Además de las nuevas propiedades de Rectangle, que están indicadas, he añadido “z” (que indica quien está encima de quien), “opacity” para permitir hacer un Item transparente, y “rotation”, que nos permite girar el Item. En cuanto a rectangle, puedes ver las propiedades respecto al borde (tanto ancho como color), “radius” que te permite redondear tu rectángulo y “gradient” para definir un gradiente, que siempre va de la parte superior a la inferior, con lo que si quieres cambiarlo de dirección, tendrás que girar el objeto.

Label

Hereda entre otros de Text, y permite escribir texto. Ejemplo:


    Label {
       id: title
       font.family: "Arial"
       font.pixelSize: units.gu(6)
       text: "Ubuntu"
       color: "red"
       anchors {
           verticalCenter: test1.verticalCenter
           horizontalCenter: test1.horizontalCenter
       }
       rotation: 45
       opacity: 0.5
    }

Con un resultado como éste:

0195_Ventana sin título.png

De entre las diferentes propiedades de Text, que como indico es de donde hereda Label, existen dos muy interesantes, contentHeight y contentWidth, que nos indican el alto y ancho, respectivamente del texto. No me quiero extender en las propiedades de Text, pero si que es interesante jugar con ellas para ver los diferentes resultados y todo lo que podemos hacer.

TextField

Es el objeto que permite al usuario introducir texto y números. En este caso, TextField, al igual que Label corresponden al Toolkit de Ubuntu, aunque heredan de QtQuick. Algunas de las posibilidades con TextField, las puedes ver en el siguiente ejemplo (prácticamente autoexplicativo):


import QtQuick 2.0
import Ubuntu.Components 0.1

Rectangle {
    id: root
    width: units.gu(60)
    height: units.gu(30)
    /*color: "lightgray"*/

    TextField {
        id: text1
        anchors.top: parent.top
        anchors.horizontalCenter: parent.horizontalCenter
        placeholderText: "Haz clic aquí"
    }
    TextField {
        id: text2
        anchors.top: text1.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        placeholderText: "Sin botón para limpiar"
        hasClearButton: false
    }
    TextField {
        id: text3
        anchors.top: text2.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        placeholderText: "Introduce tu contraseña"
        echoMode: TextInput.Password
    }
    TextField {
        id: text4
        anchors.top: text3.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        placeholderText: "De solo lectura"
        readOnly: true
    }
    TextField {
        id: text5
        errorHighlight: false
        anchors.top: text4.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        inputMask:'99.999.999-A;_'
    }
    TextField {
        errorHighlight: false
        id: text6
        anchors.top: text5.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        placeholderText: "Longitud limitada"
        maximumLength:10
    }
}

0196_Ventana sin título.png

Button

Con este objeto permitiremos al usuario que interactué con la aplicación. Al igual que los anteriores, también es un objeto perteneciente al toolkit de Ubuntu, y puedes ver alguna de sus características en el siguiente ejemplo:


import QtQuick 2.0
import Ubuntu.Components 0.1

Rectangle {
    id: root
    width: units.gu(60)
    height: units.gu(30)
    color: "palegoldenrod"
    Column {
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.verticalCenter: parent.verticalCenter
            spacing: units.gu(3)
            Button {
                width: units.gu(30)
                text: "Haz clic aquí"
                onClicked: print("Has pulsado el primer botón")
            }
            Button {
                width: units.gu(30)
                iconSource: "icon.png"
                color: "green"
                onClicked: print("Has pulsado el segundo botón")
                rotation: 15
                antialiasing: true
                z: 1
            }
            Button {
                width: units.gu(30)
                iconSource: "icon.png"
                text: "Un icono a la izquierda"
                iconPosition: "left"
                onClicked: print("Has pulsado el tercer botón")
                onPressAndHold: print('Mantienes pulsado el tercer botón')
            }
    }
}

y que da como resultado:

0197_Ventana sin título.png

De este ejemplo, quiero destacar el uso de Column, que es un objeto de QtQuick, que nos permite poner diferentes objetos en forma de columna, y la posibilidad de introducir imágenes dentro de los botónes con tan solo indicar la dirección. Para utilizar la imagen tiene que estar en el mismo directorio que el archivo “qml” o bien referida a el de forma relativa.

Conclusiones

En este artículo hemos realizado un repaso de los diferentes objetos disponibles para desarrollar nuestras aplicaciones, como se comportan y como trabajar con ellos. El siguiente paso, que veremos en el próximo artículo, tratará directamente con la programación de eventos mediante Javascript, que nos permitrá interactuar entre los distintos objetos de nuestra interfaz y el usuario.

Más información | QtQuick, Ubuntu