Sur cette page

Attributs des objets QML

Chaque type d’objet QML dispose d’un ensemble défini d’attributs. Chaque instance d’un type d’objet est créée avec l’ensemble d’attributs qui ont été définis pour ce type d’objet. Il existe plusieurs types d’attributs pouvant être spécifiés, qui sont décrits ci-dessous.

Attributs dans les déclarations d’objets

Une déclaration d’objet dans un document QML définit un nouveau type. Elle déclare également une hiérarchie d’objets qui sera instanciée si une instance de ce type nouvellement défini est créée.

L'ensemble des types d'attributs des types d'objets QML est le suivant :

  • l'attribut id
  • les attributs de propriété
  • les attributs de signal
  • les attributs de gestionnaire de signal
  • les attributs de méthode
  • propriétés associées et attributs de gestionnaires de signaux associés
  • attributs d'énumération

Ces attributs sont décrits en détail ci-dessous.

L'attribut id

Un élément QML peut posséder au maximum un attribut id. Cet attribut est fourni par le langage lui-même et ne peut être redéfini ni remplacé par aucun type d’objet QML.

Une valeur peut être attribuée à l’attribut `id` d’une instance d’objet afin de permettre à cet objet d’être identifié et référencé par d’autres objets. Cette « id » doit commencer par une lettre minuscule ou un trait de soulignement, et ne peut contenir que des lettres, des chiffres et des traits de soulignement. Elle ne doit pas non plus correspondre à un mot-clé JavaScript. Consultez la spécification du langage ECMAScript pour obtenir la liste de ces mots-clés.

Si vous utilisez dans QML un nom qui ne convient pas comme identifiant JavaScript, tel que « as », vous ne pourrez pas faire référence à l’objet identifié en JavaScript, ce qui rendra l’identifiant pratiquement inutile. Vous pouvez toutefois toujours utiliser l’ QQmlContext depuis C++ pour interagir avec ces identifiants.

Vous trouverez ci-dessous un objet « TextInput » et un objet « Text ». La valeur de la propriété « id » de l’objet « TextInput » est définie sur « myTextInput ». L’objet « Text » définit sa propriété « text » pour qu’elle ait la même valeur que la propriété « text » de l’objet « TextInput », en se référant à « myTextInput.text ». Désormais, les deux éléments afficheront le même texte :

import QtQuick

Column {
    width: 200; height: 200

    TextInput { id: myTextInput; text: "Hello World" }

    Text { text: myTextInput.text }
}

Un objet peut être référencé par son id depuis n’importe quel endroit du contexte QML dans lequel il a été créé. Par conséquent, une valeur id doit toujours être unique au sein de son contexte. Voir Portée et résolution des noms pour plus d’informations.

Le contexte est également exposé au C++ via la hiérarchie des QQmlContext. Vous pouvez, par exemple, récupérer le contexte d’un objet spécifique via la fonction qmlContext et demander d’autres objets dans le même contexte :

QObject *textInput = qmlContext(theColumn)->objectForName("myTextInput");

Une fois qu’une instance d’objet est créée, la valeur de son attribut id ne peut plus être modifiée. Bien qu’il puisse ressembler à une propriété ordinaire, l’attribut id n’ est pas un attribut property classique, et une sémantique particulière s’y applique ; par exemple, il n’est pas possible d’accéder à myTextInput.id dans l’exemple ci-dessus.

Attributs de propriété

Une propriété est un attribut d’un objet auquel on peut attribuer une valeur statique ou lier une expression dynamique. La valeur d’une propriété peut être lue par d’autres objets. En général, elle peut également être modifiée par un autre objet, à moins qu’un type QML particulier n’ait explicitement interdit cette modification pour une propriété spécifique.

Définition des attributs de propriété

Une propriété peut être définie pour un type en C++ en enregistrant une instance de la classe ` Q_PROPERTY `, qui est ensuite enregistrée dans le système de types QML. Il est également possible de définir une propriété personnalisée d’un type d’objet dans une déclaration d’objet d’un document QML à l’aide de la syntaxe suivante :

[default] [virtual] [override] [final] [required] [readonly] property <propertyType> <propertyName>

De cette manière, une déclaration d’objet peut exposer une valeur particulière à des objets externes ou gérer plus facilement un état interne.

Les noms de propriétés doivent commencer par une lettre minuscule et ne peuvent contenir que des lettres, des chiffres et des traits de soulignement. Les mots réservés de JavaScript ne constituent pas des noms de propriétés valides. Les mots-clés default, required, readonly, virtual, override et final sont facultatifs et modifient la sémantique de la propriété déclarée. Reportez-vous aux sections suivantes consacrées aux propriétés par défaut, aux propriétés obligatoires, aux propriétés en lecture seule et à la sémantique de redéfinition pour plus d’informations sur leur signification respective.

La déclaration d’une propriété personnalisée crée implicitement un signal de changement de valeur pour cette propriété, ainsi qu’un gestionnaire de signal associé appelé on<PropertyName>Changed, où <PropertyName> est le nom de la propriété, dont la première lettre est en majuscule.

Par exemple, la déclaration d’objet suivante définit un nouveau type dérivé du type de base Rectangle. Il comporte deux nouvelles propriétés, avec un gestionnaire de signal implémenté pour l’une d’entre elles :

Rectangle {
    property color previousColor
    property color nextColor
    onNextColorChanged: console.log("The next color will be: " + nextColor.toString())
}
Types valides dans les définitions de propriétés personnalisées

Tous les types de valeur QML peuvent être utilisés comme types de propriétés personnalisées. Par exemple, voici des déclarations de propriétés toutes valides :

Item {
    property int someNumber
    property string someString
    property url someUrl
}

(Les valeurs d’énumération sont simplement des nombres entiers et peuvent être référencées à l’aide du type ` int ` à la place.)

Certains types de valeurs sont fournis par le module ` QtQuick ` et ne peuvent donc pas être utilisés comme types de propriété tant que ce module n’est pas importé. Consultez la documentation sur les types de valeurs QML pour plus de détails.

Notez que le type de valeur ` var ` est un type générique de remplacement pouvant contenir n’importe quel type de valeur, y compris des listes et des objets :

property var someNumber: 1.5
property var someString: "abc"
property var someBool: true
property var someList: [1, 2, "three", "four"]
property var someObject: Rectangle { width: 100; height: 100; color: "red" }

De plus, n’importe quel type d’objet QML peut être utilisé comme type de propriété. Par exemple :

property Item someItem
property Rectangle someRectangle

Cela s’applique également aux types QML personnalisés. Si un type QML a été défini dans un fichier nommé ColorfulButton.qml (dans un répertoire qui a ensuite été importé par le client), alors une propriété de type ColorfulButton serait également valide.

Attribution de valeurs aux attributs de propriété

La valeur d'une propriété d'une instance d'objet peut être spécifiée de deux manières distinctes :

  • une affectation de valeur lors de l’initialisation
  • une affectation de valeur impérative

Dans les deux cas, la valeur peut être soit une valeur statique, soit la valeur d’une expression de liaison.

Affectation de valeur lors de l'initialisation

La syntaxe permettant d’attribuer une valeur à une propriété lors de l’initialisation est la suivante :

<propertyName> : <value>

Une affectation de valeur lors de l’initialisation peut, si on le souhaite, être combinée avec une définition de propriété dans une déclaration d’objet. Dans ce cas, la syntaxe de la définition de propriété devient :

[default] property <propertyType> <propertyName> : <value>

Voici un exemple d’initialisation de la valeur d’une propriété :

import QtQuick

Rectangle {
    color: "red"
    property color nextColor: "blue" // combined property declaration and initialization
}
Affectation de valeur impérative

Une affectation de valeur impérative consiste à attribuer une valeur (valeur statique ou expression de liaison) à une propriété à partir d’un code JavaScript impératif. La syntaxe d’une affectation de valeur impérative correspond simplement à l’opérateur d’affectation JavaScript, comme illustré ci-dessous :

[<objectId>.]<propertyName> = value

Voici un exemple d’affectation de valeur impérative :

import QtQuick

Rectangle {
    id: rect
    Component.onCompleted: {
        rect.color = "red"
    }
}

Valeurs statiques et valeurs d’expressions de liaison

Comme indiqué précédemment, deux types de valeurs peuvent être attribuées à une propriété : les valeurs statiques et les valeurs d’expressions de liaison. Ces dernières sont également appelées « liaisons de propriété ».

TypeSémantique
Valeur statiqueValeur constante qui ne dépend pas d’autres propriétés.
Expression de liaisonExpression JavaScript décrivant la relation d'une propriété avec d'autres propriétés. Les variables de cette expression sont appelées les dépendances de la propriété.

Le moteur QML assure le respect de la relation entre une propriété et ses dépendances. Lorsque la valeur d’une des dépendances change, le moteur QML réévalue automatiquement l’expression de liaison et attribue le nouveau résultat à la propriété.

Voici un exemple illustrant les deux types de valeurs attribuées aux propriétés :

import QtQuick

Rectangle {
    // both of these are static value assignments on initialization
    width: 400
    height: 200

    Rectangle {
        // both of these are binding expression value assignments on initialization
        width: parent.width / 2
        height: parent.height
    }
}

Remarque : pour attribuer une expression de liaison de manière impérative, celle-ci doit être contenue dans une fonction transmise à ` Qt.binding()`, puis la valeur renvoyée par `Qt.binding()` doit être attribuée à la propriété. En revanche, `Qt.binding()` ne doit pas être utilisé lors de l’attribution d’une expression de liaison lors de l’initialisation. Voir Liaison de propriétés pour plus d’informations.

Sécurité des types

Les propriétés sont sécurisées au niveau des types. Une propriété ne peut se voir attribuer qu’une valeur correspondant à son type.

Par exemple, si une propriété est de type int et que vous essayez de lui attribuer une chaîne de caractères, vous obtiendrez une erreur :

property int volume: "four"  // generates an error; the property's object will not be loaded

De même, si une valeur de type incorrect est attribuée à une propriété pendant l’exécution, la nouvelle valeur ne sera pas prise en compte et une erreur sera générée.

Certains types de propriétés ne disposent pas d’une représentation naturelle des valeurs ; pour ces types de propriétés, le moteur QML effectue automatiquement une conversion de chaîne de caractères en valeur de type. Ainsi, par exemple, même si les propriétés de type « color » stockent des couleurs et non des chaînes de caractères, vous pouvez attribuer la chaîne « "red" » à une propriété de couleur sans qu’aucune erreur ne soit signalée.

Consultez la section « Types de valeurs QML » pour obtenir la liste des types de propriétés pris en charge par défaut. De plus, tout type d’objet QML disponible peut également être utilisé comme type de propriété.

Types de propriétés spéciaux

Attributs des propriétés de liste d’objets

Une propriété de type « list » peut se voir attribuer une liste de valeurs de type objet QML. La syntaxe permettant de définir une valeur de liste d’objets consiste en une liste séparée par des virgules et placée entre crochets :

[ <item 1>, <item 2>, ... ]

Par exemple, le type « Item » dispose d’une propriété « states » qui sert à contenir une liste d’objets de type « State ». Le code ci-dessous initialise la valeur de cette propriété avec une liste de trois objets « State » :

import QtQuick

Item {
    states: [
        State { name: "loading" },
        State { name: "running" },
        State { name: "stopped" }
    ]
}

Si la liste ne contient qu’un seul élément, les crochets peuvent être omis :

import QtQuick

Item {
    states: State { name: "running" }
}

Une propriété de type « list » peut être spécifiée dans une déclaration d’objet selon la syntaxe suivante :

[default] property list<<ObjectType>> propertyName

et, comme pour les autres déclarations de propriété, l’initialisation d’une propriété peut être combinée avec la déclaration de propriété selon la syntaxe suivante :

[default] property list<<ObjectType>> propertyName: <value>

Voici un exemple de déclaration de propriété de type liste :

import QtQuick

Rectangle {
    // declaration without initialization
    property list<Rectangle> siblingRects

    // declaration with initialization
    property list<Rectangle> childRects: [
        Rectangle { color: "red" },
        Rectangle { color: "blue"}
    ]
}

Si vous souhaitez déclarer une propriété destinée à stocker une liste de valeurs qui ne sont pas nécessairement des valeurs de type objet QML, vous devez plutôt déclarer une propriété de type « var ».

Propriétés groupées

Dans certains cas, les propriétés contiennent un groupe logique d’attributs de sous-propriétés. Ces attributs de sous-propriétés peuvent être assignés soit à l’aide de la notation par points, soit à l’aide de la notation de groupe.

Par exemple, le type ` Text ` possède une propriété ` font `. Ci-dessous, le premier objet ` Text ` initialise ses valeurs ` font ` à l’aide de la notation par points, tandis que le second utilise la notation de groupe :

Text {
    //dot notation
    font.pixelSize: 12
    font.bold: true
}

Text {
    //group notation
    font { pixelSize: 12; bold: true }
}

La syntaxe des propriétés groupées est disponible pour toute propriété dont le type possède ses propres sous-propriétés. Il s’agit d’une notation, et non d’un type de propriété distinct : que la propriété soit de type valeur (comme ` font `) ou de type objet, cela n’a aucune incidence sur la syntaxe.

Le type de la propriété a toutefois une incidence sur ce que le moteur doit faire :

  • Si la propriété contient un type de valeur, le moteur lit la valeur, la modifie, puis la réécrit. La propriété doit donc être accessible en écriture.
  • Si la propriété contient un type objet, les affectations sont écrites dans l’objet que la propriété contient actuellement. Cet objet ne doit pas être nul lorsque les affectations sont appliquées. La propriété elle-même peut être en lecture seule ou modifiable. La rendre en lecture seule permet d’empêcher le code QML de remplacer l’objet auquel appartiennent les sous-propriétés, évitant ainsi toute confusion quant à l’objet auquel s’appliquent les propriétés groupées. C’est généralement une bonne idée.

Les noms des sous-propriétés sont résolus par rapport au type déclaré de la propriété, et non par rapport au type de l’objet qu’elle contient au moment de l’exécution. Vous ne pouvez pas non plus utiliser les deux formes pour la même propriété dans la même définition d’objet : soit vous attribuez un objet à la propriété, soit vous effectuez des affectations à ses sous-propriétés.

Alias de propriétés

Les alias de propriété sont des propriétés qui contiennent une référence à une autre propriété. Contrairement à une définition de propriété ordinaire, qui alloue un nouvel espace de stockage unique à la propriété, un alias de propriété relie la propriété nouvellement déclarée (appelée « propriété d’alias ») en tant que référence directe à une propriété existante (la « propriété aliásée »).

Une déclaration d’alias de propriété ressemble à une définition de propriété ordinaire, à l’exception qu’elle nécessite le mot-clé ` alias ` à la place d’un type de propriété, et que le membre droit de la déclaration de propriété doit être une référence d’alias valide :

[default] property alias <name>: <alias reference>

Contrairement à une propriété ordinaire, un alias est soumis aux restrictions suivantes :

  • Il ne peut faire référence qu’à un objet, ou à la propriété d’un objet, se trouvant dans la portée du type au sein duquel l’alias est déclaré.
  • Il ne peut pas contenir d’expressions JavaScript arbitraires
  • Il ne peut pas faire référence à des objets déclarés en dehors de la portée de son type.
  • La référence d’alias n’est pas facultative, contrairement à la valeur par défaut facultative d’une propriété ordinaire ; la référence d’alias doit être fournie lors de la première déclaration de l’alias.
  • Il ne peut pas faire référence à des propriétés attachées.
  • Elle ne peut pas faire référence à des propriétés situées au sein d’une hiérarchie d’une profondeur égale ou supérieure à 3. Le code suivant ne fonctionnera pas :
    property alias color: myItem.myRect.border.color
    
    Item {
        id: myItem
        property Rectangle myRect
    }

    En revanche, les alias vers des propriétés situées jusqu’à deux niveaux de profondeur fonctionneront.

    property alias color: rectangle.border.color
    
    Rectangle {
        id: rectangle
    }

Par exemple, voici un type « Button » (propriété de texte) avec une propriété aliasée « buttonText » (propriété de texte) qui est liée à l’objet « text » (propriété de texte) de l’enfant « Text » :

// Button.qml
import QtQuick

Rectangle {
    property alias buttonText: textItem.text

    width: 100; height: 30; color: "yellow"

    Text { id: textItem }
}

Le code suivant permettrait de créer un ` Button ` avec une chaîne de texte définie pour l’objet enfant ` Text ` :

Button { buttonText: "Click Me" }

Ici, la modification de « buttonText » modifie directement la valeur de « textItem.text » ; elle ne modifie pas une autre valeur qui mettrait ensuite à jour « textItem.text ». Si buttonText n’était pas un alias, la modification de sa valeur ne changerait en réalité pas du tout le texte affiché, car les liaisons de propriétés ne sont pas bidirectionnelles : la valeur de buttonText aurait changé si textItem.text avait été modifié, mais pas l’inverse.

Alias de propriétés et types

Les alias de propriété ne peuvent pas avoir de spécifications de type explicites. Le type d’un alias de propriété est le type déclaré de la propriété ou de l’objet auquel il fait référence. Par conséquent, si vous créez un alias vers un objet référencé via son `id` et comportant des propriétés supplémentaires déclarées en ligne, ces propriétés supplémentaires ne seront pas accessibles via l’alias :

// MyItem.qml
Item {
    property alias inner: innerItem

    Item {
        id: innerItem
        property int extraProperty
    }
}

Vous ne pouvez pas initialiser ` inner.extraProperty ` depuis l'extérieur de ce composant, car `inner` n'est qu'un alias ( Item) :

// main.qml
MyItem {
    inner.extraProperty: 5 // fails
}

Cependant, si vous extrayez l’objet `inner` dans un composant distinct avec un fichier .qml dédié, vous pouvez instancier ce composant à la place et disposer de toutes ses propriétés via l’alias :

// MainItem.qml
Item {
    // Now you can access inner.extraProperty, as inner is now an ExtraItem
    property alias inner: innerItem

    ExtraItem {
        id: innerItem
    }
}

// ExtraItem.qml
Item {
    property int extraProperty
}

Propriétés par défaut

Une définition d’objet peut comporter une seule propriété par défaut. Lorsqu’un objet est imbriqué directement à l’intérieur d’un autre objet sans qu’aucune propriété ne soit spécifiée, il se voit automatiquement attribuer la propriété par défaut de l’objet qui l’englobe.

La déclaration d’une propriété avec le mot-clé facultatif « default » la désigne comme propriété par défaut. Par exemple, supposons qu’il existe un fichier Framer.qml avec une propriété par défaut « focusItem » :

// Framer.qml
import QtQuick

Row {
    default property Item focusItem
    property Item leftItem: Rectangle {
        width: 10
        height: parent.height
        color: "red"
    }
    property Item rightItem: Rectangle {
        width: 10
        height: parent.height
        color: "blue"
    }
    children: [leftItem, focusItem, rightItem]
}

La valeur « focusItem » peut être attribuée dans une définition d’objet « Framer », comme ceci :

Framer {
    Text { text: "Hello, world!" }
}

Cela a exactement le même effet que ce qui suit :

Framer {
    focusItem: Text { text: "Hello, world!" }
}

Cependant, comme la propriété « focusItem » a été marquée comme propriété par défaut, il n’est pas nécessaire d’attribuer explicitement l’objet « Text » à cette propriété.

Bien qu’une propriété de n’importe quel type puisse être marquée comme propriété « default », il n’est généralement utile de marquer ainsi que les propriétés de type « var », de type « object » et leurs types de séquence respectifs : Comme seules les instances d’objet sont attribuées à la propriété par défaut, il n’y a aucun intérêt, en QML, à disposer par exemple d’une propriété de type chaîne « default ».

Considérons le type `TextHolder` suivant :

// TextHolder.qml
Item {
    property default string mytext
}

En soi, cela fonctionne correctement. Cependant, il n’est pas possible d’attribuer un littéral de chaîne à mytext sans mentionner explicitement le nom de la propriété :

TextHolder {
  /* The following would be a syntax error, and will not assign
     to the mytext property:
  "some text"

  The line below is the only way to assign the value:
  \1/
  mytext: "some text"
}

Vous remarquerez que des objets enfants peuvent être ajoutés à n’importe quel type dérivé de ` Item` sans avoir à les ajouter explicitement à la propriété ` children `. Cela s’explique par le fait que la propriété par défaut de ` Item ` est sa propriété ` data `, et que tout élément ajouté à cette liste pour un ` Item ` est automatiquement ajouté à sa liste ` children`.

Les propriétés par défaut peuvent s’avérer utiles pour réaffecter les enfants d’un élément. Par exemple :

Item {
    default property alias content: inner.children

    Item {
        id: inner
    }
}

En définissant la propriété par défaut alias sur inner.children, tout objet attribué comme enfant de l’élément externe est automatiquement réattribué comme enfant de l’élément interne.

Avertissement : la définition des valeurs de la propriété de liste par défaut d’un élément peut se faire de manière implicite ou explicite. Au sein de la définition d’un même élément, ces deux méthodes ne doivent pas être mélangées, car cela entraîne un ordre indéfini des éléments dans la liste.

Item {
    // Use either implicit or explicit assignement to the default list property but not both!
    Rectangle { width: 40 }            // implicit
    data: [ Rectangle { width: 100 } ] // explicit
}

Sémantique de redéfinition

Par défaut, les propriétés peuvent être masquées: vous redéclarez une propriété dans un type QML dérivé, éventuellement avec un nouveau type et de nouveaux attributs. Il en résulte deux propriétés portant le même nom, dont une seule est accessible dans un contexte donné. C'est rarement ce que vous souhaitez. Souvent, c’est accidentel, et la plupart du temps, les effets sont assez déroutants. De plus, le masquage nuit à l’utilisation des outils.

Pour remédier à cela, les mots-clés ` virtual`, ` override`, ` final `, ainsi que des avertissements et des erreurs supplémentaires, ont été introduits.

Pour plus de détails et un ensemble complet d’exemples, y compris les avertissements et les erreurs, consultez la page « Masquage des propriétés et sémantique de redéfinition ».

Propriétés obligatoires

Une déclaration d’objet peut définir une propriété comme obligatoire à l’aide du mot-clé « required ». La syntaxe est la suivante :

required property <propertyType> <propertyName>

Comme son nom l’indique, les propriétés obligatoires doivent être définies lors de la création d’une instance de l’objet. Le non-respect de cette règle empêchera le démarrage des applications QML si cela peut être détecté de manière statique. Dans le cas de composants QML instanciés dynamiquement (par exemple via ` Qt.createComponent()`), le non-respect de cette règle entraîne un avertissement et une valeur de retour nulle.

Il est possible de rendre obligatoire une propriété existante à l’aide de

required <propertyName>

L'exemple suivant montre comment créer un composant Rectangle personnalisé, dans lequel la propriété « color » doit toujours être spécifiée.

// ColorRectangle.qml
Rectangle {
    required color
}

Remarque : vous ne pouvez pas attribuer de valeur initiale à une propriété obligatoire depuis le QML, car cela irait directement à l’encontre de l’usage prévu des propriétés obligatoires.

Les propriétés obligatoires jouent un rôle particulier dans le code modèle-vue-délégué : si le délégué d’une vue possède des propriétés obligatoires dont les noms correspondent aux noms de rôle du modèle de la vue, ces propriétés seront alors initialisées avec les valeurs correspondantes du modèle. Pour plus d’informations, consultez la page « Modèles et vues » sur Qt Quick.

Consultez les pages QQmlComponent::createWithInitialProperties, QQmlApplicationEngine::setInitialProperties et QQuickView::setInitialProperties pour découvrir comment initialiser les propriétés obligatoires depuis le C++.

Propriétés en lecture seule

Une déclaration d’objet peut définir une propriété en lecture seule à l’aide du mot-clé ` readonly `, selon la syntaxe suivante :

readonly property <propertyType> <propertyName> : <value>

Les propriétés en lecture seule doivent se voir attribuer une valeur statique ou une expression de liaison lors de leur initialisation. Une fois qu’une propriété en lecture seule a été initialisée, vous ne pouvez plus modifier sa valeur statique ni son expression de liaison.

Par exemple, le code figurant dans le bloc « Component.onCompleted » ci-dessous n’est pas valide :

Item {
    readonly property int someNumber: 10

    Component.onCompleted: someNumber = 20  // TypeError: Cannot assign to read-only property
}

Remarque : une propriété en lecture seule ne peut pas être également une propriété par défaut.

Objets modificateurs de propriété

Les propriétés peuvent être associées à des objets modificateurs de valeur de propriété. La syntaxe permettant de déclarer une instance d’un type de modificateur de propriété associé à une propriété particulière est la suivante :

<PropertyModifierTypeName> on <propertyName> {
    // attributes of the object instance
}

On parle généralement de syntaxe « on ».

Il est important de noter que la syntaxe ci-dessus est en fait une déclaration d’objet qui instanciera un objet agissant sur une propriété préexistante.

Certains types de modificateurs de propriété peuvent ne s’appliquer qu’à des types de propriétés spécifiques, mais cela n’est pas imposé par le langage. Par exemple, le type « NumberAnimation » fourni par QtQuick n’animera que les propriétés de type numérique (telles que int ou real). Tenter d’utiliser un « NumberAnimation » avec une propriété non numérique ne provoquera pas d’erreur, mais la propriété non numérique ne sera pas animée. Le comportement d’un type de modificateur de propriété lorsqu’il est associé à un type de propriété particulier est défini par son implémentation.

Attributs de signal

Un signal est une notification émise par un objet pour signaler qu’un événement s’est produit : par exemple, une propriété a changé, une animation a démarré ou s’est arrêtée, ou encore une image a été téléchargée. Le type ` MouseArea `, par exemple, dispose d’un signal ` clicked ` qui est émis lorsque l’utilisateur clique dans la zone de la souris.

Un objet peut être notifié via un gestionnaire de signal chaque fois qu’un signal particulier est émis. Un gestionnaire de signal est déclaré à l’aide de la syntaxe on<Signal>, où <Signal> est le nom du signal, dont la première lettre est en majuscule. Le gestionnaire de signal doit être déclaré au sein de la définition de l’objet qui émet le signal, et il doit contenir le bloc de code JavaScript à exécuter lorsque le gestionnaire de signal est appelé.

Par exemple, le gestionnaire de signal onClicked ci-dessous est déclaré dans la définition de l’objet MouseArea et est appelé lorsque l’on clique sur le bouton « MouseArea », ce qui entraîne l’affichage d’un message dans la console :

import QtQuick

Item {
    width: 100; height: 100

    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("Click!")
        }
    }
}

Définition des attributs de signal

Un signal peut être défini pour un type en C++ en enregistrant une instance de ` Q_SIGNAL ` d’une classe, qui est ensuite enregistrée auprès du système de types QML. Il est également possible de définir un signal personnalisé pour un type d’objet dans une déclaration d’objet d’un document QML à l’aide de la syntaxe suivante :

signal <signalName>[([<parameterName>: <parameterType>[, ...]])]

Tenter de déclarer deux signaux ou méthodes portant le même nom dans le même bloc de type constitue une erreur. Cependant, un nouveau signal peut réutiliser le nom d’un signal existant sur le type. (Cette opération doit être effectuée avec prudence, car le signal existant risque d’être masqué et de devenir inaccessible.)

Voici trois exemples de déclarations de signaux :

import QtQuick

Item {
    signal clicked
    signal hovered()
    signal actionPerformed(action: string, actionResult: int)
}

Vous pouvez également spécifier les paramètres d’un signal en utilisant la syntaxe de type « propriété » :

signal actionCanceled(string action)

Afin d'assurer la cohérence avec les déclarations de méthodes, il est préférable d'utiliser les déclarations de type avec des deux-points.

Si le signal ne comporte aucun paramètre, les parenthèses « () » sont facultatives. Si des paramètres sont utilisés, leurs types doivent être déclarés, comme pour les arguments string et int du signal actionPerformed ci-dessus. Les types de paramètres autorisés sont les mêmes que ceux répertoriés dans la section « Définition des attributs de propriété » de cette page.

Pour émettre un signal, appelez-le en tant que méthode. Tous les gestionnaires de signal concernés seront appelés lorsque le signal sera émis, et les gestionnaires peuvent utiliser les noms d’arguments de signal définis pour accéder aux arguments respectifs.

Signaux de changement de propriété

Les types QML fournissent également des signaux de changement de propriété intégrés qui sont émis chaque fois qu’une valeur de propriété change, comme décrit précédemment dans la section consacrée aux attributs de propriété. Reportez-vous à la section suivante sur les gestionnaires de signaux de changement de propriété pour plus d’informations sur l’utilité de ces signaux et sur leur utilisation.

Attributs des gestionnaires de signaux

Les gestionnaires de signaux constituent un type particulier d’attribut de méthode, dans lequel l’implémentation de la méthode est appelée par le moteur QML chaque fois que le signal associé est émis. L’ajout d’un signal à la définition d’un objet en QML ajoute automatiquement un gestionnaire de signal associé à cette définition, dont l’implémentation est, par défaut, vide. Les clients peuvent fournir une implémentation pour mettre en œuvre la logique du programme.

Prenons l’exemple du type ` SquareButton ` suivant, dont la définition est fournie dans le fichier ` SquareButton.qml ` comme indiqué ci-dessous, avec les signaux ` activated ` et ` deactivated` :

// SquareButton.qml
Rectangle {
    id: root

    signal activated(xPosition: real, yPosition: real)
    signal deactivated

    property int side: 100
    width: side; height: side

    MouseArea {
        anchors.fill: parent
        onReleased: root.deactivated()
        onPressed: mouse => root.activated(mouse.x, mouse.y)
    }
}

Ces signaux peuvent être reçus par n’importe quel objet de type ` SquareButton ` dans un autre fichier QML du même répertoire, où les implémentations des gestionnaires de signaux sont fournies par le client :

// myapplication.qml
SquareButton {
    onDeactivated: console.log("Deactivated!")
    onActivated: (xPosition, yPosition) => {
        console.log(`Activated at ${xPosition}, ${yPosition}`)
    }
}

Les gestionnaires de signaux n’ont pas besoin de déclarer les types de leurs paramètres, car ceux-ci sont déjà spécifiés par le signal. La syntaxe des fonctions fléchées illustrée ci-dessus ne prend pas en charge les annotations de type.

Consultez la section Système d’événements « Signal et gestionnaire » pour plus de détails sur l’utilisation des signaux.

Gestionnaires de signaux de modification de propriété

Les gestionnaires de signaux pour les changements de propriété adoptent la syntaxe on<Property>Changed, où <Property> est le nom de la propriété, dont la première lettre est en majuscule. Par exemple, bien que la documentation sur le type ` TextInput ` ne mentionne pas de signal ` textChanged `, ce signal est implicitement disponible du fait que ` TextInput ` dispose d’une propriété ` text ` ; il est donc possible d’écrire un gestionnaire de signal ` onTextChanged ` qui sera appelé chaque fois que cette propriété change :

import QtQuick

TextInput {
    text: "Change this!"

    onTextChanged: console.log(`Text has changed to: ${text}`)
}

Attributs de méthode

Une méthode d’un type d’objet est une fonction qui peut être appelée pour effectuer un traitement ou déclencher d’autres événements. Une méthode peut être connectée à un signal de sorte qu’elle soit automatiquement invoquée chaque fois que le signal est émis. Voir Système d’événements de signaux et de gestionnaires pour plus de détails.

Définition des attributs de méthode

Une méthode peut être définie pour un type en C++ en marquant une fonction d’une classe, qui est ensuite enregistrée auprès du système de types QML à l’aide de ` Q_INVOKABLE `, ou en l’enregistrant en tant qu’ Q_SLOT e de la classe. Il est également possible d’ajouter une méthode personnalisée à la déclaration d’un objet dans un document QML à l’aide de la syntaxe suivante :

function <functionName>([<parameterName>[: <parameterType>][, ...]]) [: <returnType>] { <body> }

Des méthodes peuvent être ajoutées à un type QML afin de définir des blocs de code JavaScript autonomes et réutilisables. Ces méthodes peuvent être appelées soit en interne, soit par des objets externes.

Contrairement aux signaux, les types de paramètres des méthodes n’ont pas besoin d’être déclarés, car leur type par défaut est « var ». Il est toutefois recommandé de les déclarer afin d’aider qmlcachegen à générer un code plus performant et d’améliorer la maintenabilité.

Tenter de déclarer deux méthodes ou signaux portant le même nom dans le même bloc de type génère une erreur. Cependant, une nouvelle méthode peut réutiliser le nom d’une méthode existante du type. (Cette opération doit être effectuée avec prudence, car la méthode existante risque d’être masquée et de devenir inaccessible.)

Voici un exemple d’ Rectangle e comportant une méthode ` calculateHeight() ` qui est appelée lors de l’affectation de la valeur ` height ` :

import QtQuick
Rectangle {
    id: rect

    function calculateHeight(): real {
        return rect.width / 2;
    }

    width: 100
    height: calculateHeight()
}

Si la méthode possède des paramètres, ceux-ci sont accessibles par leur nom au sein de la méthode. Ci-dessous, lorsque l’on clique sur l’ MouseArea, cela invoque la méthode moveTo() qui peut alors se référer aux paramètres reçus newX et newY pour repositionner le texte :

import QtQuick

Item {
    width: 200; height: 200

    MouseArea {
        anchors.fill: parent
        onClicked: mouse => label.moveTo(mouse.x, mouse.y)
    }

    Text {
        id: label

        function moveTo(newX: real, newY: real) {
            label.x = newX;
            label.y = newY;
        }

        text: "Move me!"
    }
}

Propriétés associées et gestionnaires de signaux associés

Les propriétés associées et les gestionnaires de signaux associés sont des mécanismes qui permettent d’annoter des objets avec des propriétés ou des gestionnaires de signaux supplémentaires qui ne seraient autrement pas disponibles pour l’objet. Ils permettent notamment aux objets d’accéder à des propriétés ou à des signaux qui sont spécifiquement pertinents pour l’objet en question.

Une implémentation de type QML peut choisir de créer un type attaché en C++ avec des propriétés et des signaux particuliers. Des instances de ce type peuvent ensuite être créées et attachées à des objets spécifiques lors de l’exécution, ce qui permet à ces objets d’accéder aux propriétés et aux signaux du type d’attachement. On y accède en préfixant les propriétés et les gestionnaires de signaux respectifs avec le nom du type d’attachement.

Les références aux propriétés et gestionnaires attachés respectent la syntaxe suivante :

<AttachingType>.<propertyName>
<AttachingType>.on<SignalName>

Par exemple, le type ` ListView ` dispose d’une propriété attachée ` ListView.isCurrentItem ` qui est accessible à chaque objet délégué dans une ` ListView`. Celle-ci peut être utilisée par chaque objet délégué individuellement pour déterminer s’il s’agit de l’élément actuellement sélectionné dans la vue :

import QtQuick

ListView {
    width: 240; height: 320
    model: 3
    delegate: Rectangle {
        width: 100; height: 30
        color: ListView.isCurrentItem ? "red" : "yellow"
    }
}

Dans ce cas, le nom du type d'attachement est « ListView » et la propriété en question est « isCurrentItem » ; par conséquent, la propriété attachée est désignée par « ListView.isCurrentItem ».

Un gestionnaire de signal associé est désigné de la même manière. Par exemple, le gestionnaire de signal associé « Component.onCompleted » est couramment utilisé pour exécuter du code JavaScript une fois le processus de création d’un composant terminé. Dans l’exemple ci-dessous, une fois que le composant « ListModel » a été entièrement créé, son gestionnaire de signal « Component.onCompleted » sera automatiquement appelé pour remplir le modèle :

import QtQuick

ListView {
    width: 240; height: 320
    model: ListModel {
        id: listModel
        Component.onCompleted: {
            for (let i = 0; i < 10; i++) {
                append({ Name: `Item ${i}` })
            }
        }
    }
    delegate: Text { text: index }
}

Étant donné que le nom du type attachant est « Component » et que ce type dispose d’un signal « completed », le gestionnaire de signal attaché est appelé « Component.onCompleted ».

Remarque concernant l’accès aux propriétés et aux gestionnaires de signaux attachés

Une erreur courante consiste à supposer que les propriétés et les gestionnaires de signaux attachés sont directement accessibles depuis les enfants de l’objet auquel ces attributs ont été attachés. Ce n’est pas le cas. L’instance du type d’attachement n’est attachée qu’à des objets spécifiques, et non à l’objet et à tous ses enfants.

Par exemple, voici une version modifiée de l’exemple précédent impliquant des propriétés attachées. Cette fois-ci, le délégué est un ` Item ` et l’ Rectangle, de couleur, est un enfant de cet élément :

import QtQuick

ListView {
    width: 240; height: 320
    model: 3
    delegate: Item {
        width: 100; height: 30

        Rectangle {
            width: 100; height: 30
            color: ListView.isCurrentItem ? "red" : "yellow" // WRONG! This won't work.
        }
    }
}

Cela ne fonctionne pas comme prévu car ` ListView.isCurrentItem ` n’ est attaché qu’ à l’objet délégué racine, et non à ses enfants. Étant donné que le ` Rectangle ` est un enfant du délégué, et non le délégué lui-même, il ne peut pas accéder à la propriété attachée ` isCurrentItem ` en tant que ` ListView.isCurrentItem`. Le rectangle doit donc accéder à ` isCurrentItem ` via le délégué racine :

ListView {
    delegate: Item {
        id: delegateItem
        width: 100; height: 30

        Rectangle {
            width: 100; height: 30
            color: delegateItem.ListView.isCurrentItem ? "red" : "yellow" // correct
        }
    }
}

Désormais, delegateItem.ListView.isCurrentItem fait correctement référence à la propriété attachée isCurrentItem du délégué.

Attributs d’énumération

Les énumérations fournissent un ensemble fixe de choix nommés. Elles peuvent être déclarées en QML à l’aide du mot-clé enum:

// MyText.qml
Text {
    enum TextType {
        Normal,
        Heading
    }
}

Comme indiqué ci-dessus, les types d'énumération (par exemple TextType) et les valeurs (par exemple Normal) doivent commencer par une majuscule.

On fait référence aux valeurs via <Type>.<EnumerationType>.<Value> ou <Type>.<Value>.

// MyText.qml
Text {
    enum TextType {
        Normal,
        Heading
    }

    property int textType: MyText.TextType.Normal

    font.bold: textType === MyText.TextType.Heading
    font.pixelSize: textType === MyText.TextType.Heading ? 24 : 12
}

Pour plus d'informations sur l'utilisation des énumérations en QML, consultez la documentation consacrée aux énumérations QML.

La possibilité de déclarer des énumérations en Qml a été introduite dans Qt 5.10.

© 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.