I. Création d'un composant personnalisé▲
Un composant est toujours défini dans un fichier qui a pour nom de base le nom du composant et l'extension .qml. Par exemple, le composant Photo sera défini dans le fichier Photo.qml. Un nom de composant commence toujours par une lettre majuscule, à laquelle s'ajoutent zéro ou plusieurs lettres (majuscules ou minuscules), nombres et tirets bas.
On effectue les étapes suivantes pour créer le composant Photo :
- copie du contenu du fichier QML BasicSteps 4.qmlBasicSteps 4.qml dans le fichier Components.qml ;
- création d'un nouveau fichier QML Photo.qml dans le même répertoire que Components.qml ;
- copie du Rectangle de la première photo dans Photo.qml.
On est assez proche du composant Photo final : on doit juste introduire des propriétés pour les paramètres du composant Photo, comme la position x, le fichier image et le titre de l'image. On va assigner des valeurs concrètes à ces propriétés dans l'instanciation du composant Photo dans Components.qml.
On n'a rien à effectuer pour la position x parce qu'un Rectangle a déjà la propriété x. On retire seulement le fragment de code x: 0;. Tant qu'on y est, on retire également le fragment de code y: 0 parce que la valeur par défaut de la position y est, de toute façon, 0.
Pour le fichier image et le titre, on introduit deux propriétés, imageFile et imageTitle, au début du Rectangle. Finalement, on remplace la valeur de source dans Image par imageFile et la valeur de text dans Text par imageTitle. Avec tous ces changements, le composant Photo ressemble à ceci :
// File: Photo.qml
import
Qt
4.7
Rectangle
{
property
url
imageFile
property
string
imageTitle
width
:
frameSize; height
:
frameSize
color
:
frameColor
Image
{
x
:
leftMargin; y
:
topMargin
source
:
imageFile
}
Text
{
x
:
0
; y
:
frameSize -
bottomMargin
text
:
imageTitle
font.pixelSize
:
fontSize
width
:
frameSize; horizontalAlignment
:
Text.AlignHCenter
height
:
bottomMargin; verticalAlignment
:
Text.AlignVCenter
}
}
On peut désormais utiliser le nouveau composant Photo dans le document QML principal, Components.qml (anciennement BasicSteps_4.qml), qui affiche trois photos côte à côte. Le code résultant ressemble à cela :
// File: Components.qml
import
Qt
4.7
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 {
x
:
0
imageFile
:
"voringsfossen1.jpg"
imageTitle
:
"Voringsfossen"
}
Photo {
x
:
frameSize
imageFile
:
"bergen.jpg"
imageTitle
:
"Bergen"
}
Photo {
x
:
2
*
frameSize
imageFile
:
"cotton_grass.jpg"
imageTitle
:
"Cotton Grass"
}
}
Dans les trois instances du composant Photo, on assigne uniquement des valeurs à trois paramètres : la position x, le fichier image et le titre de l'image. Les valeurs des autres propriétés telles que frameSize ou leftMargin sont propagées depuis l'instance racine de Rectangle jusqu'aux instances de Photo et leurs instances enfants, Image et Text.
On peut dès lors admirer notre travail en lançant la visionneuse QML dans le répertoire de Components.qml et de Photo.qml :
qmlviewer Components.qml &
Comment la visionneuse QML sait-elle où trouver le composant Photo ? Par défaut, elle cherche un fichier QML d'extension .qml avec le même nom de base que le composant dans le répertoire où elle est lancée. Dans ce cas, elle trouve le fichier Photo.qml. On montrera dans le module Modules comment placer les composants dans d'autres répertoires que celui-ci.
II. Les alias et les id de propriétés▲
On peut toujours améliorer un petit peu le composant Photo. L'URL du fichier image et le titre de l'image sont stockés en deux endroits pour chacun. Le fichier image est stocké dans la propriété imageFile, tout juste introduite, et dans la propriété source de Image. De même, le titre de l'image est stocké dans imageTitle et dans text de Text. Cela signifie que la mémoire est allouée deux fois pour le fichier image et deux fois pour le titre de l'image. Ce n'est pas un gros problème pour cet exemple. Si, cependant, les objets dupliqués étaient plus gros, cela deviendrait problématique. Un autre souci que l'on a est que l'on doit garantir que les deux occurrences du fichier image et du titre de l'image soient synchronisées. De même, c'est peu gênant pour ce petit programme, mais cela devient délicat pour des programmes plus gros.
Heureusement, les alias de propriété viennent à notre secours. Un alias de propriété dit que deux propriétés partagent la même valeur et la stockent dans un seul espace en mémoire. L'équivalent C++ serait une référence à une variable existante. La syntaxe d'un alias de propriété est :
property
alias
property1
:
property2
où property1 est l'alias venant d'être introduit et property2, la propriété existante sur laquelle on souhaite faire l'alias.
Dans le composant Photo, on veut définir imageFile en tant qu'alias de la propriété source de Image et imageTitle en tant qu'alias de la propriété text de Text. Il subsiste un tout petit problème : comment peut-on aborder en une unique fois le problème des propriétés source et text ? S'il y avait plusieurs composants Image ou Text dans le composant Photo (un scénario assez commun, d'ailleurs), on n'aurait aucun moyen de les distinguer.
La propriété spéciale QML id résout ce problème. La propriété id est le nom ou identificateur unique d'une instance d'un composant. En utilisant la notation instName.propName, on peut accéder à la propriété propertyName de l'instance dont la propriété id est de valeur instName.
Dès lors, on peut enfin introduire les deux alias de propriété et les utiliser. Dans Photo.qml, on remplace les deux définitions de propriété des lignes 5 et 6 par :
property
alias
imageFile
:
photo.source
property
alias
imageTitle
:
title.text
On assigne l'identificateur photo au composant Image et retire la ligne pour la propriété source. Ainsi, Image ressemble à ceci :
Image
{
id
:
photo
x
:
leftMargin; y
:
topMargin
}
De même, on assigne les identificateurs title au composant Text et retire la ligne pour la propriété text. Ainsi, Text ressemble à ceci :
Text
{
id
:
title
x
:
0
; y
:
frameSize -
bottomMargin
font.pixelSize
:
fontSize
width
:
frameSize; horizontalAlignment
:
Text.AlignHCenter
height
:
bottomMargin; verticalAlignment
:
Text.AlignVCenter
}
Le code complet du composant Photo modifié peut être trouvé dans Photo.qmlPhoto.qml.
Il est important de noter que la valeur de id n'est pas enfermée par des guillemets. Elle n'est tout simplement pas mise sous forme de citation.
III. Divers▲
Merci à Thibaut Cuvelier et Claude Leloup pour leur relecture !