I. L'article original

Le Qt Developer Network est un réseau de développeurs utilisant Qt afin de partager leur savoir sur ce framework. Vous pouvez le consulter en anglais.

Nokia, Qt, Qt Quarterly et leurs logos sont des marques déposées de Nokia Corporation en Finlande et/ou dans les autres pays. Les autres marques déposées sont détenues par leurs propriétaires respectifs.

Cet article est la traduction de Qt Quick Tutorial: Module 1 – Basics.

II. Composants et propriétés

 
Sélectionnez
// File: BasicSteps_1.qml
 
import Qt 4.7
 
Rectangle {
  width: 300
  height: 300
  color: "blue"
}

On lance la visionneuse QML pour voir le résultat de notre travail :

 
Sélectionnez
> qmlviewer BasicSteps_1.qml &

Oui, le code QML ci-dessus produit en effet un rectangle bleu. Un tel extrait de code QML comme celui ci-dessus est appelé un document QML (voir aussi les documents QMLles documents QML). Un document QML est un morceau de code QML qui contient au moins une déclaration import et exactement un composant de haut niveau. Dans notre exemple, Rectangle est le composant unique de haut niveau. Généralement, un document QML correspond à un fichier, mais il peut également correspondre à un texte stocké dans une chaine de caractères ou une URL pointant sur un document QML stocké sur un serveur distant.

La déclaration import Qt 4.7 fait en sorte que tous les éléments QML de Qt 4.7 soient disponibles dans le document QML. Qt 4.7 vient avec des composants intégrés comme Rectangle, Text, ListView, WebView, Flipable, Animation et bien d'autres encore (voir les éléments QMLles éléments QML pour une liste complète).

Les composants sont les équivalents QML aux classes C++. Ils ont des propriétés, des méthodes (fonctions membres), des signaux et des slots. L'occurrence de Rectangle dans les lignes 5 à 9 est une instance du composant Rectangle : une instance bleue de 300 × 300 pixels d'un composant Rectangle. Dans la documentation de Qt, élément est souvent utilisé comme synonyme de composant. Les composants avec représentation visuelle comme Rectangle ou Text sont appelés des items. Les noms de composants commencent toujours avec une majuscule suivie par zéro ou plusieurs lettres, chiffres et tirets bas.

Une instance de composant est caractérisée par ses propriétés, qui sont des paires nom-valeur. L'instance de Rectangle ci-dessus a trois propriétés, width, height et color, de valeurs respectives 300, 300 et blue. Les noms de propriétés commencent toujours par une minuscule suivie par zéro ou plusieurs lettres, chiffres et tirets bas. Les propriétés sont type-safe. Par conséquent, la ligne

 
Sélectionnez
width: "Oslo"

est illégale, parce que la propriété width attend un nombre de type réel. QML supporte les types de base suivants : bool, color, date, font, int, list, point, real, rect, size, string, time, url.

Plusieurs propriétés peuvent être écrites sur une seule ligne, séparées par un point-virgule :

 
Sélectionnez
width: 300; height: 300
color: "blue"

L'ordre des propriétés n'a pas d'importance. On aurait pu écrire le Rectangle comme ceci :

 
Sélectionnez
Rectangle {
  color: "blue"
  height: 300
  width: 300
}

Et le résultat n'en serait pas changé.

Les commentaires sont marqués dans QML de la même manière qu'en C++. Les commentaires de fin de ligne commencent par //. La ligne 1 de notre exemple contient un tel commentaire. Les commentaires multilignes commencent par /* et finissent par */.

III. Composition de composants

L'enthousiasme généré par ce rectangle bleu commence à s'estomper, n'est-ce pas ? Bien, plaçons le rectangle bleu à l'intérieur d'un cadre de photo avec une photo au centre, un titre en dessous de la photo et un cadre soyeux et coloré. On positionne un composant Image QML pour la photo et un composant Text pour le titre sur le composant Rectangle, puis on change la couleur du rectangle en la valeur RGB #FFF8DC pour le rendre soyeux.

 
Sélectionnez
// File: BasicSteps_2.qml
import Qt 4.7
 
Rectangle {
  width: 300
  height: 300
  color: "#FFF8DC"  // cornsilk
 
  Image {
    x: 10; y: 45
    source: "voringsfossen1.jpg"
  }
 
  Text {
    x: 10; y: 265
    text: "Voringsfossen"
  }
}

Le composant Image est un enfant du Rectangle et est placé à la position x 10 et 45 en y, relativement à l'origine du Rectangle (10 pixels à droite et 45 pixels en dessous du coin en haut à gauche du rectangle). Comme l'image est de dimensions 280 × 210 pixels, cette position centre l'image horizontalement et verticalement à l'intérieur du rectangle. La propriété source dit au moteur d'exécution QML de rechercher l'image, qui est stockée dans le fichier « voringsfossen1.jpg ». Le fichier image est situé dans le même répertoire que le fichier QML BasicSteps.qml. En général, la propriété source prend une URL. L'image pourrait donc être située n'importe où sur Internet ou sur le système de fichiers local.

Le Text est positionné à 10 pixels à droite et à 265 pixels en dessous du coin en haut à gauche du rectangle. Le texte affiché est « Voringsfossen », qui est le nom de la cascade la plus haute et la plus connue de Norvège. À nouveau, Text est un enfant de Rectangle.

Cet exemple simple d'un cadre de photo montre comment utiliser des composants basiques pour en former un plus complexe. Les composants ou plus exactement parlant les instances de composants sont arrangées dans un arbre. Dans notre exemple, le Rectangle est le tronc de l'arbre tandis que Image et Text sont les branches du tronc, les enfants. Les enfants peuvent également avoir leurs propres enfants et ainsi de suite. Les arbres d'instances sont équivalents aux arbres d'instances d'éléments graphiques ou widgets de Qt.

Le résultat n'accordera pas de prix de design, mais c'est déjà un bon début. Améliorons-le étape par étape. Comme le titre ne devrait pas avoir l'air tassé dans le cadre en dessous de la photo, on la monte de 20 pixels. On change juste la propriété y de notre Image à 25.

 
Sélectionnez
Image {
  x: 10; y: 25
  source: "voringsfossen1.jpg"
}

On souhaite que le titre soit un peu plus gros, disons de 20 pixels (ligne 4), et on veut qu'il soit centré à la fois horizontalement (ligne 5) et verticalement (ligne 6) dans la zone située sous la photo.

 
Sélectionnez
Text {
  x: 0; y: 235
  text: "Voringsfossen"
  font.pixelSize: 20
  width: 300; horizontalAlignment: Text.AlignHCenter
  height: 65; verticalAlignment: Text.AlignVCenter
}

Il est important de noter que la propriété horizontalAlignment n'a un effet que si une width est spécifiée. Sans la longueur, le moteur d'exécution de QML ne saurait pas où positionner le texte (essayez seulement). Il en va de même pour verticalAlignment. Ainsi, à chaque fois qu'on utilise horizontalAlignment et verticalAlignment, on doit donner respectivement une longueur et une hauteur.

IV. Propriétés personnalisées

Avant de créer nos propres propriétés, on doit leur trouver un besoin réel auquel elles répondent. Le but suivant est de montrer trois photos côte à côte. On atteint cet objectif en instanciant simplement trois fois la photo depuis BasicSteps_2.qml et en enfermant ces trois rectangles dans un grand rectangle (voir BasicSteps 3.qmlBasicSteps 3.qml pour le code source complet).

 
Sélectionnez
import Qt 4.7
 
Rectangle {
  width: 3 * 300; height: 300
 
  // Photo 1
  Rectangle {
    x: 0; y: 0
    ...
  }
 
  // Photo 2
  Rectangle {
    x: 300; y: 0
    ...
  }
 
  // Photo 3
  Rectangle {
    x: 2 * 300; y: 0
    ...
  }
}

Les photos 1, 2 et 3 sont des copies identiques de Rectangle depuis BasicSteps_2.qml, à l'exception des propriétés x et y. La position des rectangles de photo est relative au rectangle d'enfermement, qui fait trois fois la longueur d'un unique rectangle de photo et la même hauteur. Les photos sont placées aux positions x 0, 300 et 600 et à la position y 0, puisqu'ils doivent apparaître côte à côte. Comme nous le voyons dans les lignes 5 et 21, on peut utiliser arbitrairement des expressions JavaScript pour les valeurs de propriétés. Dans l'exemple, on utilise les expressions 3 * 300 et 2 * 300.

Avec ces changements, on voit la même photo trois fois. En changeant les propriétés source et text, on peut facilement changer l'image et le titre de chaque photo.

Le code n'est pas bien écrit et sent fort les lourdes duplications de code. On va éliminer ces dernières par le biais des trois rectangles de photos quasi identiques dans le module suivant, « les composants ». On résoudra les duplications par le biais du bon moyen remplaçant les nombres magiques tels que 300, 25, 65 ou 20 - par l'introduction de propriétés.

La pire offense est le nombre magique 300 qui apparaît treize fois. Ainsi, si on veut changer la taille de nos cadres de photo à, disons, 400, on doit effectuer treize changements - et on va logiquement oublier au moins une occurrence. La solution est l'introduction d'une propriété frameSize au début du gros rectangle et de remplacer chaque occurrence de 300 par frameSize. De même, on élimine les nombres magiques 10, 25 et 65 en introduisant respectivement les propriétés leftMargin, topMargin et bottomMargin ainsi qu'en remplaçant chaque occurrence de ces nombres magiques par ces propriétés. On repère également que 235 = 300 – 65 = frameSize – bottomMargin et on remplace chaque occurrence de 235 par l'expression frameSize – bottomMargin. Tant qu'on y est, on remplace également la valeur RGB « #FFF8DC » par la propriété frameColor. Après toutes ces modifications, le code du rectangle d'enfermement et les photos ont l'aspect suivant (voir BasicSteps 4.qmlBasicSteps 4.qml pour le code complet) :

 
Sélectionnez
Rectangle {
  property int frameSize: 300
  property int leftMargin: 10
  property int topMargin: 25
  property int bottomMargin: 65
  property int fontSize: 20
  property color frameColor: "#FFF8DC"  // cornsilk
 
  width: 3 * frameSize; height: frameSize
 
  ...
 
  // Photo 3
  Rectangle {
    x: 2 * frameSize; y: 0
    width: frameSize; height: frameSize
    color: frameColor
 
    Image {
      x: leftMargin; y: topMargin
      source: "cotton_grass.jpg"
    }
 
    Text {
      x: 0; y: frameSize - bottomMargin
      text: "Cotton Grass"
      font.pixelSize: fontSize
      width: frameSize; horizontalAlignment: Text.AlignHCenter
      height: bottomMargin; verticalAlignment: Text.AlignVCenter
    }
  }

La syntaxe générale pour une propriété personnalisée est :

 
Sélectionnez
property <type> <name>[: <value>]

Le mot-clé property est suivi par le nom du type, <type>, et le nom de la propriété, <name>. La valeur par défaut de la propriété, <value>, est optionnelle. Par exemple, la ligne

 
Sélectionnez
property int frameSize: 300

définit une propriété du nom de frameSize, qui est de type entier et a une valeur par défaut de 300.

Jusqu'ici, on a couvert le sujet des règles des propriétés parce qu'elles fonctionnaient comme on le voulait. Les propriétés d'une instance parente sont accessibles par les instances enfants, les petits-enfants et ainsi de suite pour la totalité de l'arborescence des instances. C'est pour cela que, par exemple, la propriété leftMargin peut être utilisée dans le composant Image du petit-enfant du Rectangle ultrapériphérique, où elle est définie. Pour le moment, on peut fonctionner avec cette règle de portée, que l'on va modifier au besoin.

V. Divers