Tag browsing: QML

SubteGo

October 15th, 2011

SubteGo, es una guiá para el servicio de Subte (Metro, Subway) de Capital Federal (Buenos Aires, Argentina), SubteGo es una aplicación para Symbian^3, desarrollada con Qt haciendo uso extensivo de QML y de Qt Components para la UI, de Qt Webkit y el API de Nokia Maps (ex Ovi Maps) para la parte de mapas y de Offline Storage para persistir los datos.

La aplicación ya esta disponible para su descarga desde Nokia Store de forma gratuita, una versión para MeeGo esta en proceso de ser enviada para su aprobación por el equipo de QA en Nokia Store.

El código fuente tanto de la versión para Symbian como el de la versión para MeeGo, va a estar disponible luego de que las dos aplicaciones hayan sido aprobadas por Nokia Store.

SubteGo es un proyecto que nació como un experimento (por eso forma parte de los labs) con el objeto de crear una aplicación en la que pueda aplicar las ultimas novedades de Qt y conocer el proceso de aprobación de aplicaciones que lleva a cabo Nokia Store, también tenia como objetivo el que sea una aplicación útil para un gran numero de personas y que pueda ser un medio de consulta recurrente.

Espero que la aplicación les sea útil si es que la descargan, y que el código fuente que pronto sera liberado les permita aprender un poco mas acerca de Qt y el proceso de desarrollo de aplicaciones para Symbian y MeeGo.

Download SubteGo

SubteGo

SubteGo

Announcements, Development , , , , , 5 responses

[Actualizado] Smart Installer y Qt Components, resolviendo conflictos

October 4th, 2011

Si están leyendo este post es muy posible que sea porque tienen problemas para que Smart Installer detecte e instale Qt Components, se supone que al compilar nuestro proyecto teniendo la opción de que lo haga junto con Smart Installer y que en el .pro este presente la siguiente linea de código:

# Add dependency to Symbian Qt Components
CONFIG += qtquickcomponents

Smart Installer detectara en el momento de la instalación, si el dispositivo ya cuenta con Qt Components, caso contrario se encargara de descargarlo e instalarlo, lamentablemente esto ha veces no pasa, ya que por alguna extraña razón, muchas personas (incluido yo) han estado reportado que Smart Installer ni siquiera detecta que Qt Components es una dependencia, por lo cual no lo instala y como resultado tenemos una aplicación que directamente no arranca o en el mejor de los casos arranca pero falla miserablemente en las vistas en donde se haga uso de Qt Components.

La solución

La solución ha este problema consiste en decirle a Smart Installer explícitamente que tiene a Qt Components como dependencia, para hacerlo solo debemos agregar las siguientes lineas de código al .pro de nuestro proyecto.

symbian {
    components.pkg_prerules += 
    "; Dependency to Symbian Qt Quick components" 
    "(0x200346DE), 1, 0, 0, {"Qt Quick components"}"

    DEPLOYMENT += components
}

Espero que este tip les haga ahorrar horas de trabajo y hasta un posible bochazo en la Ovi Store.

Actualización

Tal como comenta (ver abajo) Lucian Tomuta (Chief Engineer en Forum Nokia), hay una solución mas simple y elegante a este problema, solo debemos usar la siguiente línea en el .pro de nuestro proyecto.

# Add dependency to Symbian Qt Components
CONFIG += qt-components
Development , , , , 2 responses

Consumiendo JSON con QML

March 19th, 2011

Hace un tiempo escribí sobre lo fácil que es consumir XML con QML, hoy le toca el turno a JSON, consumir JSON con QML requiere un poco mas de trabajo comparado con XML, pero no mucho mas.

Pasemos al código, lo primero que haremos sera crear un archivo data.js que contendrá la lógica que poblara al Model con los datos, para este ejemplo vamos a usar el API de Wikileaks para mostrar un listado con los últimos cables liberados, lo siguiente es agregar el ListModel, el Delegate cuyo código esta al final y no necesita muchos comentarios, el ListView que mostrara los datos y vamos a disparar la función getLatestCables() cuando la view se haya cargado.

main.qml
import QtQuick 1.0
import "data.js" as Data

Rectangle {
    width:360
    height:640

    Component.onCompleted:Data.getLatestCables();

    ListModel {
        id:cablesModel
    }

    CablesDelegate {
        id:cablesDelegate
    }

    Item {
        id:cablesList
        anchors.fill:parent

        ListView {
            model:cablesModel
            delegate:cablesDelegate
            anchors.fill:parent
        }
    }
}

La magia que no es mucha, pasa aquí, esto es simple y puro JavaScript, utilizaremos un XMLHttpRequest para acceder al feed con los datos, luego lo parseamos e iremos agregando uno a uno los datos al Model.

data.js
function getLatestCables(){
    var xhr = new XMLHttpRequest;
    xhr.open("GET", "http://api.leakfeed.com/v1/cables/latest.json");
    xhr.onreadystatechange = function() {
        if (xhr.readyState == XMLHttpRequest.DONE) {
            var a = JSON.parse(xhr.responseText);
            for (var c in a) {
                var i = a[c];
                cablesModel.append({identifier: i.identifier, classification: i.classification, office: i.office, subject: i.subject});
            }
        }
    }
    xhr.send();
}
CablesDelegate.qml
import QtQuick 1.0

Component {

    Rectangle {
        border.color:"#b7b7b7"
        border.width:1
        width:parent.width
        height:cableIdentifier.height + cableOffice.height + cableClass.height + cableSubject.height + 10
        color:"#fff"

        Item {
            width:parent.width
            height:parent.height

            Grid {
                rows:4
                width:parent.width
                anchors.verticalCenter:parent.verticalCenter
                anchors.left:parent.left
                anchors.leftMargin:5
                anchors.right:parent.right
                anchors.rightMargin:5

                Text {
                    id:cableIdentifier
                    text:identifier
                    font.bold:true
                    font.pixelSize:18
                    smooth:true
                    color:"#333"
                }

                Text {
                    id:cableOffice
                    color:"#0076A3"
                    text:office
                    font.pixelSize:18
                    font.bold:true
                    smooth:true
                }

                Text {
                    id:cableClass
                    color:"#aa1317"
                    text:classification
                    font.pixelSize:16
                    font.bold:true
                    smooth:true
                }

                Text {
                    id:cableSubject
                    text:subject
                    font.pixelSize: 14
                    wrapMode:Text.WrapAtWordBoundaryOrAnywhere
                    width:parent.width
                    smooth:true
                    color:"#333"
                }
            }
        }
    }
}

Si todo sale bien, al correr la demo deberíamos obtener como resultado algo parecido a los que se ve en la siguiente imagen.

JSON & QML

Development , , , 3 responses

QML 3D

January 4th, 2011

Qt/3D es un conjunto de herramientas y funciones que permiten crear aplicaciones que hagan uso de gráficos 3D, Qt3D extiende las clases del modulo OpenGL de Qt, estas APIs facilitan escribir código que sea fácil de portar entre aplicaciones de escritorio OpenGL y aplicaciones embebidas o mobile OpenGL/ES, por ultimo pero no menos importante, contamos con un binding para utilizar Qt/3D desde QML.

Para comenzar con Qt/3D lo primero que debemos hacer es instalarlo, los pasos a seguir están muy bien explicados aquí, ya sea en Linux, Windows o Mac OS X, no son complicados, aunque puede tomar algo de tiempo el proceso.

¿Que podemos hacer con Qt/3D y QML?

Con Qt/3D podemos crear viewports, asignar luces y cámaras, crear o importar nuestros propios modelos 3D, ya sea usando las figuras básicas incluidas, creando nuestros propios meshes, o usando algún modelo ya existente en formato 3ds o bzs, también podemos crear animaciones y aplicárselas a los modelos, las cámaras y las luces.

Si han trabajado anteriormente con aplicaciones 3D todos estos términos y conceptos les sonaran familiares, lo que les permitirá reutilizar su conocimiento a la vez de que podrán rápidamente ponerse manos a la obra.

Hello World 3D

El siguiente ejemplo muestra de forma simple, algunos de los conceptos y controles que se usan en la mayoría de la aplicaciones 3D, lo primero es crear los imports correspondientes de Qt/3D, luego sigue el Viewport que define la escena 3D, así como su tamaño, las luces y las cámaras a utilizar y sus posiciones.

Luego tenemos un objeto Sphere que tiene un levelOfDetail de 10 el máximo de su tipo y que mide la cantidad de triángulos necesarios para crear el objeto, en este caso 32768, luego alineamos el objeto al eje Y, para terminar aplicándole una textura usando el elemento Effect.

Para finalizar vamos a animar el objeto 3D, para ello usaremos una Rotation3D, a la cual seteamos el eje que queremos animar y luego en una NumberAnimation establecemos la propiedad a animar, en este caso, angle.

import Qt 4.7
import Qt3D 1.0
import Qt3D.Shapes 1.0

Viewport {
    width: 640
    height: 360
    camera: Camera {
        eye: Qt.vector3d(0,0,8)
    }
    Sphere {
        levelOfDetail: 10
        axis: Qt.YAxis
        effect: Effect {
            texture: "images/land_ocean_ice_2048.jpg"
            decal: true
        }
        transform:[
            Rotation3D {
                axis: Qt.vector3d(0,1,0)
                NumberAnimation on angle {
                    running: true
                    loops: Animation.Infinite
                    from: 360
                    to: 0
                    duration: 6000
                }
            }
        ]
    }
}

Qt/3D QML Demo

Con este simple ejemplo pueden darse una idea del poder que nos brinda la combinación Qt/3D y QML, si están interesados en el tema, pueden profundizar mas en el dando un vistazo a la documentación oficial, o ver un repaso rápido de las principales características en la presentación dada por Sarah Smith en los Qt Developers Days 2010.

Development, User Interface , , 3 responses

QML Panorama

December 30th, 2010

Últimamente hay mucho revuelo y movimiento relacionado a lo que es mobile, pero de todo ese ruido muy pocas cosas son realmente originales o proponen un cambio de paradigma, una de esas excepciones es la nueva UI de Windows Phone 7 y aunque posiblemente nunca compre, use o desarrolle para WP7 hay un par de conceptos interesantes que me gustaría tomar prestados, como por ejemplo los controles Panorama (ver imagen abajo) y Pivot para poder usarlos en mis aplicaciones QML.

Panorama Control

Vamos a comenzar con el control Panorama, implementarlo no es para nada complicado, como verán hay algunas propiedades para configurar el look and feel, el contenido o el elemento que hará de contenedor de los PanoramaItems, también tenemos un control Flickable que utilizaremos para mover horizontalmente los PanoramaItems hijos y para finalizar tenemos un elemento Text que usaremos para mostrar el titulo del control Panorama y una Grid en donde se irán acomodando los PanoramaItems.

Panorama.qml
import Qt 4.7

Rectangle {
    id: container
    width:parent.width
    height:parent.height
    default property alias content: content.children
    property string title: "panorama"
    property int titleSize:48
    property string titleFont: ""
    property color titleColor:"#fff"
    property color background:"#333"
    property string backgroundImage:""
    property string backgroundFillMode:"Tile"

    color: container.background

    Flickable {
        width:parent.width
        height:parent.height
        contentWidth: content.width;
        contentHeight: container.height
        boundsBehavior: "StopAtBounds"
        Image{
            source: container.backgroundImage
            fillMode: container.backgroundFillMode
            Grid{
                width: content.width
                height: content.height
                rows:2
                Text {
                    id: title
                    text: container.title
                    font.pointSize: container.titleSize
                    font.family: container.titleFont
                    color: container.titleColor
                }
                Grid {
                    id: content
                    spacing:10
                }
            }
        }
    }
}

El control PanoramaItem es aun mas sencillo como se ve en el código a continuación.

PanoramaItem.qml
import Qt 4.7

Item {
    id: container
    default property alias content: content.children
    property string title: "panoramaItem"
    property int titleSize: 21
    property color titleColor: "#fff"

    height: wrapper.height

    Grid{
        id: wrapper
        rows:2
        Text {
            id: title
            width: container.width
            text: container.title
            smooth: true
            wrapMode: "Wrap"
            font.pointSize: container.titleSize
            color: container.titleColor
        }
        Rectangle {
            id: content
            width: container.width
            height: container.height - title.height            
        }
    }
}

Bien, ahora que ya tenemos nuestros controles, es momento de usarlos, para ello solo debemos crear un control Panorama, establecer el titulo, el tipo y tamaño del font, una imagen de fondo si es que vamos a usar una, para luego agregar los PanoramaItems que deseemos con su respectivos contenidos.

PanoramaDemo.qml
import Qt 4.7

Rectangle {
    id: screen
    width: 360
    height: 640

    Panorama{
        id:myPanorama
        title: "my Panorama"
        backgroundImage:"images/bg.jpg"
        PanoramaItem{
            width: screen.width -30
            title:"first item"
            titleSize: 21
            
            // Content here
            
        }
        PanoramaItem{
            width: screen.width
            title:"second Item"
            titleSize: 21
            
            // Content here
            
        }
        PanoramaItem{
            width: screen.width
            title:"third Item"
            titleSize: 21
            
            // Content here
  
        }
    }    
}

En la imagen a continuación pueden ver el resultado de el ejemplo y en el vídeo su funcionamiento.

QML Panorama in action

Como verán duplicar el comportamiento básico de estos controles no fue para nada difícil, aunque esto es solo un simple ejemplo, con muchas cosas aun por pulir y funcionalidades por implementar para lograr una emulación completa de las funcionalidades de los controles originales, aun sirve para demostrar la capacidades de QML y como con poco código se pueden lograr resultados interesantes.

User Interface , , , , , 2 responses