Structure d'un document QML
Un document QML est un fragment autonome de code source QML composé de trois parties :
- Une liste facultative de pragmas
- Ses instructions d’importation
- Une seule déclaration d’objet racine
Par convention, une seule ligne vide sépare les importations de la définition de la hiérarchie des objets.
Les documents QML sont toujours encodés au format UTF-8.
Pragmas
Les pragmas sont des instructions destinées au moteur QML lui-même, qui peuvent être utilisées pour spécifier certaines caractéristiques des objets dans le fichier courant ou pour modifier la façon dont le moteur interprète le code. Les pragmas suivants sont expliqués en détail ci-dessous.
| pragma | valeurs | valeur par défaut | depuis |
|---|---|---|---|
| Singleton | 5.2 | ||
| ListPropertyAssignBehavior | Ajouter | X | 6.3 |
| Remplacer | 6.3 | ||
| Remplacer si ce n'est pas la valeur par défaut | 6.3 | ||
| Comportement du composant | Lié | 6.4 | |
| Non lié | X | 6.4 | |
| Comportement de la signature de fonction | Ignoré | 6.5 | |
| Appliqué | X | 6.5 | |
| NativeMethodBehavior | AcceptThisObject | 6,5 | |
| RejeterCetObjet | X | 6,5 | |
| Comportement du type de valeur | Référence | X | 6.5 |
| Copier | 6.5 | ||
| Adressable | 6,6 | ||
| Non adressable | X | 6.6 | |
| Assertable | 6,8 | ||
| Traducteur | <contexte de traduction> | <nom de fichier> | 6,7 |
Singleton
pragma Singleton déclare le composant défini à la racine du document QML comme singleton. Voir Singletons en QML pour plus d’informations.
ListPropertyAssignBehavior
Ce pragma vous permet de définir comment les affectations aux propriétés de liste doivent être gérées dans les composants définis dans le document QML. Par défaut, l'affectation à une propriété de liste ajoute un élément à la fin de la liste. Vous pouvez demander explicitement ce comportement en utilisant la valeur Append. Vous pouvez également demander que le contenu des propriétés de liste soit toujours remplacé à l’aide de Replace, ou remplacé si la propriété n’est pas la propriété par défaut à l’aide de ReplaceIfNotDefault.
Prenons l’exemple d’un type de base dans un document Base.qml :
pragma ListPropertyAssignBehavior: ReplaceIfNotDefault
import QtQuick
Item {
objectName: "outer"
default property list<Item> d: [
Item { objectName: "inner" }
]
property list<Item> notDefault: [
Item { objectName: "one" }
]
}Si vous dérivez ensuite de Base et modifiez ses propriétés de liste, le ListPropertyAssignBehavior prend effet. Dans ce cas :
Base {
// The new item is appended to the list even though you're assigning.
// The (default) property "d" now contains "inner" and "inner2".
d: [
Item { objectName: "inner2" }
]
// The list is replaced by the list given here.
// The (non-default) property "notDefault" now contains only "two".
notDefault: [
Item { objectName: "two" }
]
}Si aucune valeur n’est fournie pour ` ListPropertyAssignBehavior ` ou si ` Append ` est spécifié, l’objet « two » sera ajouté à la propriété ` notDefault `, ce qui donnera une liste contenant à la fois « one » et « two ».
Si ` Replace ` est spécifié, le contenu de la propriété par défaut « d » sera également remplacé, ce qui donnera une liste ne contenant que « inner2 ».
Remarque : la même déclaration peut également être utilisée pour les types définis en C++, en ajoutant les macros QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_APPEND, QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE et QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE_IF_NOT_DEFAULT à la déclaration de classe. Par exemple :
class MyType : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE
Q_PROPERTY(QQmlListProperty<QObject> a READ a)
[...]
};ComponentBehavior
Vous pouvez définir plusieurs composants dans un même fichier QML. La portée racine du fichier QML est un composant, et vous pouvez en outre disposer d’éléments de type QQmlComponent, créés explicitement ou implicitement en tant que propriétés, ou encore de composants en ligne. Ces composants sont imbriqués. Chacun des composants internes se trouve au sein d’un composant externe spécifique. La plupart du temps, les identifiants définis dans un composant externe sont accessibles au sein de tous ses composants internes imbriqués. Vous pouvez toutefois créer des éléments à partir d’un composant dans n’importe quel autre contexte, avec des identifiants différents disponibles. Cela remet en cause l’hypothèse selon laquelle les identifiants externes sont disponibles. Par conséquent, le moteur et les outils QML ne peuvent généralement pas savoir à l’avance à quel type, le cas échéant, ces identifiants seront résolus lors de l’exécution.
Grâce au pragma `ComponentBehavior`, vous pouvez limiter tous les composants internes définis dans un fichier à la création d’objets uniquement au sein de leur contexte d’origine. Si un composant est lié à son contexte, vous pouvez utiliser en toute sécurité les identifiants des composants externes du même fichier au sein de ce composant. Les outils QML supposeront alors que les identifiants externes, avec leurs types spécifiques, sont disponibles.
Pour lier les composants à leur contexte, spécifiez l’argument « Bound » :
pragma ComponentBehavior: BoundCela implique qu’en cas de conflits de noms, les identifiants définis à l’extérieur d’un composant lié remplacent les propriétés locales des objets créés à partir de ce composant. Sinon, l’utilisation des identifiants ne serait en réalité pas sûre, car des versions ultérieures d’un module pourraient ajouter d’autres propriétés au composant. Si le composant n’est pas lié, les propriétés locales prennent le pas sur les identifiants définis en dehors du composant, mais pas sur ceux définis à l’intérieur du composant.
L’exemple ci-dessous affiche la propriété `r` de l’objet ` ListView ` portant l’identifiant `color`, et non la propriété `r` de la couleur du rectangle.
pragma ComponentBehavior: Bound
import QtQuick
ListView {
id: color
property int r: 12
model: 1
delegate: Rectangle {
Component.onCompleted: console.log(color.r)
}
}La valeur par défaut de ` ComponentBehavior ` est ` Unbound`. Vous pouvez également la spécifier explicitement. Dans une future version de Qt, la valeur par défaut passera à ` Bound`.
Les composants délégués liés à leur contexte ne reçoivent pas leur propre contexte privé lors de leur instanciation. Cela signifie que, dans ce cas, les données du modèle ne peuvent être transmises que via les propriétés obligatoires. La transmission de données du modèle via les propriétés de contexte ne fonctionnera pas. Cela concerne les délégués vers, par exemple, Instantiator, Repeater, ListView, TableView, GridView, TreeView et, de manière générale, tout ce qui utilise DelegateModel en interne.
Par exemple, ce qui suit ne fonctionnera pas:
pragma ComponentBehavior: Bound
import QtQuick
ListView {
delegate: Rectangle {
color: model.myColor
}
}La propriété ` delegate ` de ` ListView ` est un composant. Par conséquent, un ` Component ` est implicitement créé autour de ` Rectangle ` ici. Ce composant est lié à son contexte. Il ne reçoit pas la propriété de contexte ` model ` fournie par ` ListView`. Pour que cela fonctionne, vous devez l’écrire de la manière suivante :
pragma ComponentBehavior: Bound
import QtQuick
ListView {
delegate: Rectangle {
required property color myColor
color: myColor
}
}Vous pouvez imbriquer des composants dans un fichier QML. Le pragma s’applique à tous les composants du fichier, quel que soit leur niveau d’imbrication.
FunctionSignatureBehavior
Ce pragma vous permet de modifier la manière dont les annotations de type sur les fonctions sont gérées. Depuis Qt 6.7, les annotations de type sont respectées lors de l’appel des fonctions. Auparavant, seul le compilateur de scripts QML appliquait les annotations de type. L’interpréteur et le compilateur JIT les ignoraient. L’application systématique des annotations de type constitue un changement de comportement par rapport aux versions antérieures, car auparavant, il était possible d’appeler des fonctions avec des arguments non correspondants.
En spécifiant la valeur « Ignored », le moteur QML et le compilateur de script QML ignorent toutes les annotations de type, ce qui rétablit le comportement de l’interpréteur et du JIT antérieur à la version 6.7. Par conséquent, une moindre quantité de code est compilée en C++ à l’avance, et une plus grande partie du code doit être interprétée ou compilée par le JIT.
Spécifier la valeur « Enforced » indique explicitement la valeur par défaut : les annotations de type sont toujours appliquées.
NativeMethodBehavior
L’appel de méthodes C++ avec des objets ` this ` différents de celui à partir duquel elles ont été récupérées ne fonctionne pas, pour des raisons historiques. L’objet d’origine est utilisé comme objet ` this `. Vous pouvez autoriser l’utilisation de l’objet ` this ` donné en définissant ` pragma NativeMethodBehavior: AcceptThisObject`. La spécification de ` RejectThisObject ` conserve le comportement historique.
Vous trouverez un exemple à ce sujet dans la section consacrée aux méthodes C++ et à l’objet « this ».
ValueTypeBehavior
Ce pragma vous permet de modifier la manière dont les types de valeur et les séquences sont gérés.
En règle générale, les noms en minuscules ne peuvent pas être des noms de types dans le code JavaScript. Cela pose problème, car les noms des types de valeur sont en minuscules. Vous pouvez spécifier « Addressable » comme valeur pour ce pragma afin de remédier à cela. Si « Addressable » est spécifié, une valeur JavaScript peut être explicitement convertie en un type de valeur spécifique et nommé. Cela s'effectue à l'aide de l'opérateur « as », comme vous le feriez avec des types d'objets. De plus, vous pouvez également vérifier s'il s'agit de types de valeur à l'aide de l'opérateur « instanceof » :
pragma ValueTypeBehavior: Addressable
import QtQml
QtObject {
property var a
property real b: (a as rect).x
property bool c: a instanceof rect
property var rect // inaccessible. "rect" is a type name.
}Étant donné que « rect » dans l’exemple ci-dessus est désormais un nom de type, il masquera toutes les propriétés nommées « rect ».
Le transtypage explicite vers le type souhaité facilite l’utilisation des outils. Il permet au Qt Quick Compiler de générer du code efficace là où cela ne serait pas possible autrement. Vous pouvez utiliser qmllint pour repérer de telles occurrences.
Il existe également une valeur Inaddressable que vous pouvez utiliser pour spécifier explicitement le comportement par défaut.
Un autre attribut du pragma ` ValueTypeBehavior ` est ` Assertable`, introduit dans Qt 6.8. En raison d’une erreur dans les versions Qt 6.6 et 6.7, l’ a as rect ci-dessus vérifie non seulement si ` a ` est une ` rect `, mais construit également une ` rect ` si ` a ` est d’un type compatible. Ce n’est évidemment pas ce que devrait faire une assertion de type. Spécifier ` Assertable ` empêche ce comportement et limite les assertions de type pour les types de valeur à la seule vérification du type. Vous devriez toujours le spécifier si vous comptez utiliser des types de valeur avec ` as`. Dans tous les cas, si l'assertion de type pour un type de valeur échoue, le résultat est ` undefined`.
instanceof ne présente pas ce problème puisqu’il ne vérifie que l’héritage, et non toutes les coercitions de types possibles.
Remarque : l’utilisation de ` as ` avec les types ` int ` et ` double ` n’est pas recommandée, car selon les règles de JavaScript, le résultat de tout calcul est un nombre à virgule flottante, même s’il se trouve avoir la même valeur que son équivalent entier. À l’inverse, toute constante entière que vous déclarez en JavaScript n’est pas un `double` selon les règles de mappage de types de QML. De plus, ` int ` et ` double ` sont des mots réservés. Vous ne pouvez accéder à ces types que via des espaces de noms de types.
Les types de valeur et les séquences sont généralement traités comme des références. Cela signifie que si vous récupérez une instance de type de valeur à partir d’une propriété dans une variable locale, puis que vous modifiez cette variable locale, la propriété d’origine est également modifiée. De plus, si vous écrivez explicitement la propriété d’origine, la variable locale est également mise à jour. Ce comportement est assez contre-intuitif dans de nombreux cas, et vous ne devriez pas vous y fier. Les valeurs « Copy » et « Reference » du pragma « ValueTypeBehavior » sont des options expérimentales permettant de modifier ce comportement. Vous ne devriez pas les utiliser. Spécifier « Copy » entraîne que tous les types de valeur soient traités comme des copies réelles. Spécifier « Reference » définit explicitement le comportement par défaut.
Plutôt que d’utiliser ` Copy `, vous devriez recharger explicitement les références aux types de valeur et aux séquences chaque fois qu’elles ont pu être affectées par des effets secondaires. Des effets secondaires peuvent se produire chaque fois que vous appelez une fonction ou que vous définissez une propriété de manière impérative. qmllint fournit des conseils à ce sujet. Par exemple, dans le code suivant, la variable f est affectée par des effets secondaires après l’écriture de width. Cela s’explique par le fait qu’il peut exister une liaison dans un type dérivé ou dans un élément Binding qui met à jour font lorsque width est modifié.
import QtQuick
Text {
function a() : real {
var f = font;
width = f.pixelSize;
return f.pointSize;
}
}Pour remédier à cela, vous pouvez éviter de conserver f pendant l'opération d'écriture sur width:
import QtQuick
Text {
function a() : real {
var f = font;
width = f.pixelSize;
f = font;
return f.pointSize;
}
}Ce code peut à son tour être raccourci ainsi :
import QtQuick
Text {
function a() : real {
width = font.pixelSize;
return font.pointSize;
}
}On pourrait penser que la récupération de la propriété font est coûteuse, mais en réalité, le moteur QML actualise automatiquement les références de type valeur à chaque fois que vous les lisez. Cette approche n’est donc pas plus coûteuse que la première version, mais constitue une manière plus claire d’exprimer les mêmes opérations.
Traducteur
Ce pragma vous permet de définir le contexte des traductions dans le fichier.
pragma Translator: myTranslationContextpragma Translator: "myTranslationContext"Pour plus d’informations sur l’internationalisation avec QML, consultez la section Écrire du code source destiné à la traduction en QML.
Importations
Un document doit importer les modules ou espaces de noms de types nécessaires pour permettre au moteur de charger les types d’objets QML référencés dans le document. Par défaut, un document peut accéder à tous les types d’objets QML qui ont été définis via des fichiers « .qml » situés dans le même répertoire ; si un document doit faire référence à d’autres types d’objets, il doit importer l’espace de noms de types dans lequel ces types ont été enregistrés.
Contrairement au C ou au C++, QML ne dispose pas de préprocesseur modifiant le document avant sa présentation à l’ QML engine. Les instructions import ne copient pas et n’ajoutent pas de code au début du document, mais indiquent au moteur QML comment résoudre les références de types présentes dans le document. Toute référence de type présente dans un document QML — telle que Rectangle et ListView —, y compris celles effectuées au sein d’un bloc JavaScript ou de liaisons de propriétés, est résolue exclusivement sur la base des instructions d’importation. Au moins une instruction d’ import ation doit être présente, telle que import QtQuick 2.0.
Veuillez consulter la documentation « Syntaxe QML - Instructions d'import » pour obtenir des informations détaillées sur les importations QML.
La déclaration de l’objet racine
Un document QML décrit une hiérarchie d’objets pouvant être instanciés. Chaque définition d’objet présente une structure spécifique : elle possède un type, peut comporter un identifiant et un nom d’objet, peut comporter des propriétés, des méthodes, des signaux et des gestionnaires de signaux.
Un fichier QML ne doit contenir qu'une seule définition d'objet racine. L'exemple suivant n'est pas valide et générera une erreur :
// MyQmlFile.qml
import QtQuick 2.0
Rectangle { width: 200; height: 200; color: "red" }
Rectangle { width: 200; height: 200; color: "blue" } // invalid!En effet, un fichier .qml définit automatiquement un type QML, qui encapsule une seule définition d’objet QML. Ce point est abordé plus en détail dans la section « Documents en tant que définitions de types d’objets QML ».
Voir également Annotations de type et assertions.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.