Structure d'un document QML
Un document QML est un morceau autonome de code source QML qui se compose de trois parties :
- une liste facultative de pragmas
- Ses déclarations d'importation
- Une déclaration d'objet racine unique
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.
Les 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 du fichier en cours 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 | ||
| RemplacerSiPasParDéfaut | 6.3 | ||
| Comportement des composants | Lier | 6.4 | |
| Non lié | X | 6.4 | |
| Comportement de la signature de la fonction | Ignoré | 6.5 | |
| Appliqué | X | 6.5 | |
| NativeMethodBehavior | Accepter cet objet | 6.5 | |
| Rejeter cet objet | X | 6.5 | |
| Comportement du type de valeur | Référence | X | 6.5 |
| Copie | 6.5 | ||
| Adressable | 6.6 | ||
| Inadressable | X | 6.6 | |
| Assertable | 6.8 | ||
| Traducteur | <contexte de traduction> | <nom du fichier> | 6.7 |
Singleton
pragma Singleton déclare le composant défini à la racine du document QML comme singleton. Voir Singletons in QML pour plus d'informations.
ListPropertyAssignBehavior (comportement de la liste des propriétés)
Ce pragma permet de définir la manière dont 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 s'ajoute à 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 la valeur Replace, ou remplacé si la propriété n'est pas la propriété par défaut à l'aide de la valeur ReplaceIfNotDefault.
Considérons 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 de Base et que vous modifiez ses propriétés de liste, le comportement 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 aucun ListPropertyAssignBehavior n'est donné ou si Append est donné, l'objet "two" sera ajouté à la propriété notDefault, ce qui donnera une liste contenant à la fois "one" et "two".
Si Replace est indiqué, le contenu de la propriété par défaut "d" sera également remplacé, ce qui donnera une liste contenant uniquement "inner2".
Remarque : la même déclaration peut également être donné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 la 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 avoir plusieurs composants définis dans le même fichier QML. La portée racine du fichier QML est un composant, et vous pouvez également avoir des éléments de type QQmlComponent, explicitement ou implicitement créés en tant que propriétés, ou des composants en ligne. Ces composants sont imbriqués. Chaque composant interne se trouve à l'intérieur d'un composant externe spécifique. La plupart du temps, les identifiants définis dans un composant externe sont accessibles dans tous ses composants internes imbriqués. Vous pouvez toutefois créer des éléments à partir d'un composant dans un contexte différent, avec des identifiants différents. Ce faisant, l'hypothèse selon laquelle les ID externes sont disponibles n'est plus valable. Par conséquent, le moteur et l'outil QML ne peuvent généralement pas savoir à l'avance à quel type, le cas échéant, ces identifiants seront résolus au moment de l'exécution.
Le pragma ComponentBehavior permet de restreindre tous les composants internes définis dans un fichier à la création d'objets dans leur contexte d'origine. Si un composant est lié à son contexte, vous pouvez utiliser en toute sécurité des ID provenant de composants externes dans le même fichier au sein du composant. L'outil QML supposera alors que les ID externes avec leurs types spécifiques sont disponibles.
Pour lier les composants à leur contexte, spécifiez l'argument Bound:
pragma ComponentBehavior: Bound
Cela implique qu'en cas de conflit de noms, les ID définis en dehors d'un composant lié remplacent les propriétés locales des objets créés à partir du composant. Sinon, il ne serait pas sûr d'utiliser les identifiants, car les 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 remplacent les ID définis à l'extérieur du composant, mais pas les ID définis à l'intérieur du composant.
L'exemple ci-dessous imprime la propriété r de l'objet ListView avec 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 prochaine version de Qt XML, la valeur par défaut sera Bound.
Les composants délégués liés à leur contexte ne reçoivent pas leurs propres contextes privés lors de l'instanciation. Cela signifie que les données du modèle ne peuvent être transmises que par l'intermédiaire des propriétés requises dans ce cas. Le transfert de données de modèle via des 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, en général, tout ce qui utilise DelegateModel en interne.
Par exemple, l'exemple suivant 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. Ce composant est lié à son contexte. Il ne reçoit pas la propriété de contexte model fournie par ListView. Pour que cela fonctionne, il faudrait l'écrire de cette manière :
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, quelle que soit la profondeur de l'imbrication.
FunctionSignatureBehavior (comportement de la signature de la fonction)
Ce pragma 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 appliquées lors de l'appel de fonctions. Auparavant, seul le compilateur de scripts QML appliquait les annotations de type. L'interpréteur et le compilateur JIT les ignoraient. Le fait de toujours appliquer les annotations de type constitue un changement de comportement par rapport aux versions antérieures, puisque vous pouviez auparavant appeler des fonctions avec des arguments non concordants.
En spécifiant Ignored comme valeur, le moteur QML et le compilateur de scripts QML ignorent les annotations de type et rétablissent donc le comportement de l'interpréteur et du JIT antérieur à la version 6.7. Par conséquent, moins de code est compilé en C++ à l'avance, et plus de code doit être interprété ou compilé par JIT.
La spécification de Enforced en tant que valeur 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 ils ont été récupérés est cassé, pour des raisons historiques. L'objet original est utilisé comme objet this. Vous pouvez autoriser l'utilisation de l'objet this donné en définissant pragma NativeMethodBehavior: AcceptThisObject. En spécifiant RejectThisObject, vous conservez le comportement historique.
Vous trouverez un exemple de ce comportement dans les méthodes C++ et l'objet "this".
ValueTypeBehavior
Ce pragma permet de modifier la manière dont les types de valeurs et les séquences sont gérés.
Habituellement, les noms en minuscules ne peuvent pas être des noms de type dans le code JavaScript. C'est un problème car les noms de types de valeurs sont en minuscules. Vous pouvez spécifier Addressable comme valeur de ce pragma pour changer cela. Si Addressable est spécifié, une valeur JavaScript peut être explicitement contrainte à un type de valeur spécifique et nommé. Cela se fait à l'aide de l'opérateur as, comme vous le feriez avec les types d'objets. En outre, vous pouvez également vérifier les types de valeurs à 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. }
Puisque rect dans l'exemple ci-dessus est maintenant un nom de type, il cachera toutes les propriétés appelées rect.
Le fait d'utiliser explicitement le type désiré pour le casting facilite l'utilisation des outils. Cela peut permettre au compilateurQt Quick de générer du code efficace là où il ne pourrait pas le faire autrement. Vous pouvez utiliser qmllint pour trouver 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 Qt 6.6 et 6.7, le a as rect ci-dessus ne vérifie pas seulement si a est un rect mais construit également un rect si a est d'un type compatible. Ce n'est évidemment pas ce qu'une assertion de type devrait faire. Spécifier Assertable empêche ce comportement et restreint les assertions de type pour les types de valeur à la seule vérification du type. Vous devriez toujours le spécifier si vous allez 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 n'a pas ce problème puisqu'il ne vérifie que l'héritage, et non toutes les coercitions de type possibles.
Remarque : l'utilisation de as avec les types int et double n'est pas conseillée car, selon les règles JavaScript, le résultat de tout calcul est un nombre à virgule flottante, même s'il a la même valeur que son équivalent en nombres entiers. Inversement, toute constante entière que vous déclarez en JavaScript n'est pas un double selon les règles de correspondance des types de QML. En outre, int et double sont des mots réservés. Vous ne pouvez vous adresser à ces types que par l'intermédiaire d'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 d'une propriété dans une valeur locale, et que vous modifiez ensuite la valeur locale, la propriété d'origine est également modifiée. En outre, si vous écrivez explicitement la propriété d'origine, la valeur locale est également mise à jour. Ce comportement est assez peu 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. En spécifiant Copy, tous les types de valeurs sont traités comme des copies réelles. La valeur Reference indique explicitement le comportement par défaut.
Plutôt que d'utiliser Copy, vous devez recharger explicitement les références aux types de valeurs et aux séquences chaque fois qu'elles peuvent avoir été affectées par des effets de bord. Les effets de bord peuvent se produire chaque fois que vous appelez une fonction ou que vous définissez impérativement une propriété. qmllint fournit des conseils à ce sujet. Par exemple, dans le code suivant, la variable f est affectée par des effets de bord après l'écriture de width. Cela est dû au fait qu'il peut y avoir 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 résoudre ce problème, vous pouvez éviter de maintenir 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; } }
Cette opération peut à son tour être abrégée :
import QtQuick Text { function a() : real { width = font.pixelSize; return font.pointSize; } }
Vous pourriez supposer que la récupération de la propriété font est coûteuse, mais en fait le moteur QML rafraîchit automatiquement les références de type de valeur chaque fois que vous lisez à partir d'elles. Il ne s'agit donc pas d'une solution plus coûteuse que la première version, mais d'une manière plus claire d'exprimer les mêmes opérations.
Traducteur
Ce pragma permet de définir le contexte des traductions dans le fichier.
pragma Translator: myTranslationContext
pragma Translator: "myTranslationContext"
Pour plus d'informations sur l'internationalisation avec QML, voir Écrire le code source pour la traduction en QML.
Importations
Un document doit importer les modules ou les 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 dans les fichiers .qml du 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.
QML n'a pas de préprocesseur qui modifie le document avant sa présentation à QML engine, contrairement à C ou C++. Les déclarations import ne copient pas et ne précèdent pas le code dans le document, mais indiquent au moteur QML comment résoudre les références de type trouvées dans le document. Toute référence de type présente dans un document QML - telle que Rectangle et ListView - y compris celles faites dans un bloc JavaScript ou des liaisons de propriété, est résolue en se basant exclusivement sur les déclarations d'importation. Au moins une déclaration import doit être présente, par exemple import QtQuick 2.0.
Veuillez consulter la documentation Syntaxe QML - Déclarations d'importation pour obtenir des informations détaillées sur les importations QML.
La déclaration d'objet racine
Un document QML décrit une hiérarchie d'objets qui peuvent être instanciés. Chaque définition d'objet a une certaine structure ; elle a un type, elle peut avoir un identifiant et un nom d'objet, elle peut avoir des propriétés, elle peut avoir des méthodes, elle peut avoir des signaux et elle peut avoir des gestionnaires de signaux.
Un fichier QML ne doit contenir qu'une seule définition d'objet racine. Ce qui suit n'est pas valide et génère 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 Documents en tant que définitions de type d'objet QML.
Voir aussi 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.