Sur cette page

Conversion des types de données entre QML et C++

Lorsque des valeurs de données sont échangées entre QML et C++, elles sont converties par le moteur QML afin d'avoir les types de données appropriés pour une utilisation en QML ou en C++. Pour ce faire, les données échangées doivent être d'un type reconnaissable par le moteur.

Le moteur QML fournit un support intégré pour un grand nombre de types de données C++ de Qt. En outre, des types C++ personnalisés peuvent être enregistrés dans le système de types QML afin d'être mis à la disposition du moteur.

Pour plus d'informations sur le C++ et les différentes méthodes d'intégration QML, voir la page de présentation de l'intégration C++ et QML.

Cette page traite des types de données pris en charge par le moteur QML et de la manière dont ils sont convertis entre QML et C++.

Propriété des données

Lorsque des données sont transférées de C++ vers QML, elles restent toujours la propriété de C++. L'exception à cette règle est lorsqu'un QObject est renvoyé par un appel de méthode C++ explicite : dans ce cas, le moteur QML assume la propriété de l'objet, à moins que la propriété de l'objet ait été explicitement définie pour rester avec C++ en invoquant QQmlEngine::setObjectOwnership() avec QQmlEngine::CppOwnership spécifié.

En outre, le moteur QML respecte la sémantique normale QObject de propriété des parents des objets Qt C++, et ne supprimera jamais une instance QObject qui a un parent.

Types de données Qt de base

Par défaut, QML reconnaît les types de données Qt suivants, qui sont automatiquement convertis en un type de valeur QML correspondant lorsqu'ils sont transmis de C++ à QML et vice-versa :

Note : Les classes fournies par le module Qt GUI telles que QColor, QFont, QQuaternion et QMatrix4x4, ne sont disponibles à partir de QML que lorsque le module Qt Quick est inclus.

Par commodité, nombre de ces types peuvent être spécifiés en QML par des valeurs de chaîne ou par une méthode connexe fournie par l'objet QtQml::Qt. Par exemple, la propriété Image::sourceSize est de type size (qui se traduit automatiquement par le type QSize ) et peut être spécifiée par une valeur de chaîne formatée comme "widthxheight", ou par la fonctionsize():

Item {
    Image { sourceSize: "100x200" }
    Image { sourceSize: Qt.size(100, 200) }
}

Pour plus d'informations, voir la documentation relative à chaque type dans la rubrique Types de valeurs QML.

Types dérivés de QObject

Toute classe dérivée de QObject peut être utilisée comme type pour l'échange de données entre QML et C++, à condition que la classe ait été enregistrée dans le système de types de QML.

Le moteur permet l'enregistrement de types instanciables et non instanciables. Une fois qu'une classe est enregistrée comme type QML, elle peut être utilisée comme type de données pour l'échange de données entre QML et C++. Voir Enregistrer les types C++ avec le système de types QML pour plus de détails sur l'enregistrement des types.

Conversion entre les types Qt et JavaScript

Le moteur QML dispose d'un support intégré pour la conversion d'un certain nombre de types Qt en types JavaScript apparentés, et vice-versa, lors du transfert de données entre QML et C++. Il est ainsi possible d'utiliser ces types et de les recevoir en C++ ou en JavaScript sans avoir à mettre en œuvre des types personnalisés permettant d'accéder aux valeurs des données et à leurs attributs.

(Notez que l'environnement JavaScript de QML modifie les prototypes d'objets JavaScript natifs, y compris ceux de String, Date et Number, afin de fournir des fonctionnalités supplémentaires. Voir l'environnement hôte JavaScript pour plus de détails).

QVariantList et QVariantMap vers JavaScript Array-like et Object

Le moteur QML assure la conversion automatique des types entre QVariantList et les tableaux JavaScript, ainsi qu'entre QVariantMap et les objets JavaScript.

Un array-like, en termes ECMAScript, est un objet utilisé comme un tableau. Les array-likes produits par conversion à partir de QVariantList (et d'autres conteneurs séquentiels C++) ne sont pas seulement cela, mais offrent également les méthodes de tableau communes et synchronisent automatiquement la propriété length. Ils peuvent être utilisés comme les tableaux JavaScript à toutes fins pratiques. La méthode Array.isArray() renvoie toujours false pour eux, cependant.

Par exemple, la fonction définie en QML ci-dessous attend deux arguments, un tableau et un objet, et imprime leur contenu en utilisant la syntaxe JavaScript standard pour l'accès aux éléments des tableaux et des objets. Le code C++ ci-dessous appelle cette fonction, en passant un QVariantList et un QVariantMap, qui sont automatiquement convertis en valeurs JavaScript de type tableau et objet, respectivement :

QML
// MyItem.qml
Item {
    function readValues(anArray, anObject) {
        for (var i=0; i<anArray.length; i++)
            console.log("Array item:", anArray[i])

        for (var prop in anObject) {
            console.log("Object item:", prop, "=", anObject[prop])
        }
    }
}
C++
// C++
QQuickView view(QUrl::fromLocalFile("MyItem.qml"));

QVariantList list;
list << 10 << QColor(Qt::green) << "bottles";

QVariantMap map;
map.insert("language", "QML");
map.insert("released", QDate(2010, 9, 21));

QMetaObject::invokeMethod(view.rootObject(), "readValues",
        Q_ARG(QVariant, QVariant::fromValue(list)),
        Q_ARG(QVariant, QVariant::fromValue(map)));

Le résultat est le suivant :

Array item: 10
Array item: #00ff00
Array item: bottles
Object item: language = QML
Object item: released = Tue Sep 21 2010 00:00:00 GMT+1000 (EST)

De même, si un type C++ utilise un type QVariantList ou QVariantMap pour un type de propriété ou un paramètre de méthode, la valeur peut être créée en tant que tableau ou objet JavaScript dans QML, et est automatiquement convertie en QVariantList ou QVariantMap lorsqu'elle est transmise à C++.

Depuis Qt 6.5, QVariantList les propriétés des types C++ peuvent être modifiées en place par le code QML. Depuis Qt 6.9, les propriétés QVariantMap des types C++ peuvent être modifiées par le code QML.

QDateTime vers JavaScript Date

Le moteur QML assure la conversion automatique des types entre les valeurs QDateTime et les objets JavaScript Date.

Par exemple, la fonction définie en QML ci-dessous attend un objet JavaScript Date et renvoie également un nouvel objet Date avec la date et l'heure actuelles. Le code C++ ci-dessous appelle cette fonction en transmettant une valeur QDateTime qui est automatiquement convertie par le moteur en un objet Date lorsqu'elle est transmise à la fonction readDate(). À son tour, la fonction readDate() renvoie un objet Date qui est automatiquement converti en valeur QDateTime lorsqu'il est reçu en C++ :

QML
// MyItem.qml
Item {
    function readDate(dt) {
        console.log("The given date is:", dt.toUTCString());
        return new Date();
    }
}
C++
// C++QQuickView view(QUrl::fromLocalFile("MyItem.qml")) ;QDateTime dateTime = QDateTime::currentDateTime() ;QDateTime retValue ;QMetaObject::invokeMethod(view.rootObject(), "readDate",Q_RETURN_ARG(QVariant, retValue),Q_ARG(QVariant, QVariant::fromValue(dateTime)) ;)
qDebug() << "Value returned from readDate():" << retValue;

De même, si un type C++ utilise QDateTime pour un type de propriété ou un paramètre de méthode, la valeur peut être créée en tant qu'objet JavaScript Date dans QML et est automatiquement convertie en valeur QDateTime lorsqu'elle est transmise à C++.

Note : Attention à la différence de numérotation des mois : JavaScript numérote le mois de janvier de 0 à 11 pour le mois de décembre, avec un décalage d'une unité par rapport à la numérotation de Qt qui numérote le mois de janvier de 1 à 12 pour le mois de décembre.

Note : Lorsque vous utilisez une chaîne en JavaScript comme valeur d'un objet Date, notez qu'une chaîne sans champ temporel (donc une simple date) est interprétée comme le début UTC du jour concerné, contrairement à new Date(y, m, d) qui utilise le début de l'heure locale du jour. La plupart des autres méthodes de construction d'un objet Date en JavaScript produisent une heure locale, à moins d'utiliser des méthodes dont le nom contient UTC. Si votre programme est exécuté dans une zone située derrière l'UTC (nominalement à l'ouest du premier méridien), l'utilisation d'une chaîne de caractères ne contenant que la date conduira à un objet Date dont la valeur getDate() est inférieure d'une unité au nombre de jours de votre chaîne de caractères ; la valeur de getHours() sera typiquement élevée. Les variantes UTC de ces méthodes, getUTCDate() et getUTCHours(), donneront les résultats que vous attendez pour de tels objets Date. Voir également la section suivante.

QDate et JavaScript Date

Le moteur QML convertit automatiquement le type QDate et le type JavaScript Date en représentant la date par le début UTC de son jour. Une date est renvoyée à QDate via QDateTime, en sélectionnant sa méthode date(), en utilisant la forme horaire locale de la date, sauf si la forme UTC coïncide avec le début du jour suivant, auquel cas c'est la forme UTC qui est utilisée.

Cette disposition légèrement excentrique permet de contourner le fait que la construction par JavaScript d'un objet Date à partir d'une chaîne de caractères ne contenant que la date utilise le début du jour UTC, alors que new Date(y, m, d) utilise le début de la date indiquée à l'heure locale, comme indiqué dans une note à la fin de la section précédente.

Par conséquent, lorsqu'une propriété ou un paramètre QDate est exposé à QML, il convient d'être prudent lors de la lecture de sa valeur : les méthodes Date.getUTCFullYear(), Date.getUTCMonth() et Date.getUTCDate() sont plus susceptibles de fournir les résultats attendus par les utilisateurs que les méthodes correspondantes sans UTC dans leur nom.

Il est donc généralement plus robuste d'utiliser une propriété QDateTime. Cela permet de contrôler, du côté de QDateTime, si la date (et l'heure) est spécifiée en termes d'UTC ou d'heure locale ; tant que le code JavaScript est écrit pour fonctionner avec la même norme, il devrait être possible d'éviter les problèmes.

QTime et JavaScript Date

Le moteur QML assure la conversion automatique des valeurs QTime en objets JavaScript Date. Comme les valeurs QTime ne contiennent pas de composant date, un composant date est créé uniquement pour la conversion. Vous ne devez donc pas vous fier à la composante date de l'objet Date qui en résulte.

Sous le capot, la conversion d'un objet JavaScript Date en QTime se fait en convertissant un objet QDateTime (en utilisant l'heure locale) et en appelant sa méthode time().

Type de séquence vers tableau JavaScript

Voir QML Sequence Types pour une description générale des types de séquence. Le site QtQml module contient quelques types de séquences que vous pouvez utiliser.

Vous pouvez également créer une structure de données de type liste en construisant un QJSValue à l'aide de QJSEngine::newArray(). Un tel tableau JavaScript ne nécessite aucune conversion lorsqu'il est transmis entre QML et C++. Voir QJSValue#Working With Arrays pour plus de détails sur la manière de manipuler les tableaux JavaScript à partir de C++.

QByteArray vers ArrayBuffer JavaScript

Le moteur QML assure la conversion automatique des types entre les valeurs QByteArray et les objets JavaScript ArrayBuffer.

Types de valeurs

Certains types de valeurs dans Qt, comme QPoint, sont représentés en JavaScript comme des objets qui ont les mêmes propriétés et fonctions que dans l'API C++. La même représentation est possible avec les types de valeurs C++ personnalisés. Pour activer un type de valeur personnalisé avec le moteur QML, la déclaration de la classe doit être annotée avec Q_GADGET. Les propriétés destinées à être visibles dans la représentation JavaScript doivent être déclarées avec Q_PROPERTY. De même, les fonctions doivent être marquées avec Q_INVOKABLE. Il en va de même pour les API C++ basées sur QObject. Par exemple, la classe Actor ci-dessous est annotée comme gadget et possède des propriétés :

class Actor
{
    Q_GADGET
    Q_PROPERTY(QString name READ name WRITE setName)
public:
    QString name() const { return m_name; }
    void setName(const QString &name) { m_name = name; }

private:
    QString m_name;
};

Q_DECLARE_METATYPE(Actor)

Le modèle habituel consiste à utiliser une classe de gadget comme type de propriété ou à émettre un gadget comme argument de signal. Dans ce cas, l'instance de gadget est transmise par valeur entre C++ et QML (car il s'agit d'un type de valeur). Si le code QML modifie une propriété d'un gadget, le gadget entier est recréé et renvoyé au définisseur de propriété C++. Dans Qt 5, les types de gadgets ne peuvent pas être instanciés par déclaration directe en Qtml. En revanche, une instance de QObject peut être déclarée ; et les instances de QObject sont toujours transmises par pointeur de C++ à QML.

Types d'énumération

Pour utiliser une énumération personnalisée comme type de données, sa classe doit être enregistrée et l'énumération doit également être déclarée avec Q_ENUM() pour l'enregistrer dans le méta-système d'objets de Qt. Par exemple, la classe Message ci-dessous possède une énumération Status:

class Message : public QObject
{
    Q_OBJECT
    Q_PROPERTY(Status status READ status NOTIFY statusChanged)
public:
    enum Status {
        Ready,
        Loading,
        Error
    };
    Q_ENUM(Status)
    Status status() const;
signals:
    void statusChanged();
};

Si la classe Message a été enregistrée dans le système de types QML, son énumération Status peut être utilisée à partir de QML :

Message {
     onStatusChanged: {
         if (status == Message.Ready)
             console.log("Message is loaded!")
     }
 }

Pour utiliser un enum comme type flags en QML, voir Q_FLAG().

Remarque : les noms des valeurs des enums doivent commencer par une lettre majuscule pour être accessibles en QML.

...
enum class Status {
          Ready,
          Loading,
          Error
}
Q_ENUM(Status)
...

Les classes d'énumération sont enregistrées dans QML en tant que propriétés scopées et non scopées. La valeur Ready sera enregistrée comme Message.Status.Ready et Message.Ready.

Lors de l'utilisation de classes d'énumération, il peut y avoir plusieurs énumérations utilisant les mêmes identifiants. L'enregistrement non cadré sera remplacé par le dernier enum enregistré. Pour les classes qui contiennent de telles confusions de noms, il est possible de désactiver l'enregistrement non chiffré en annotant votre classe à l'aide d'une macro spéciale Q_CLASSINFO. Utilisez le nom RegisterEnumClassesUnscoped avec la valeur false pour éviter que les enums scopés ne soient fusionnés dans le même espace de noms.

class Message : public QObject
    {
        Q_OBJECT
        Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
        Q_ENUM(ScopedEnum)
        Q_ENUM(OtherValue)

    public:
        enum class ScopedEnum {
              Value1,
              Value2,
              OtherValue
        };
        enum class OtherValue {
              Value1,
              Value2
        };
    };

Les enums de types apparentés sont généralement enregistrés dans la portée du type apparenté. Par exemple, tout enum d'un type différent utilisé dans une déclaration Q_PROPERTY entraîne la mise à disposition de tous les enums de ce type dans QML. Il s'agit généralement plus d'un inconvénient que d'une caractéristique. Pour éviter que cela ne se produise, annotez votre classe avec une macro spéciale Q_CLASSINFO. Utilisez le nom RegisterEnumsFromRelatedTypes avec la valeur false pour empêcher les enums de types apparentés d'être enregistrés dans ce type.

Vous devriez enregistrer explicitement les types englobants de tout enum que vous souhaitez utiliser en QML, en utilisant QML_ELEMENT ou QML_NAMED_ELEMENT, plutôt que de compter sur l'injection de leurs enums dans d'autres types.

class OtherType : public QObject
{
    Q_OBJECT
    QML_ELEMENT

public:
    enum SomeEnum { A, B, C };
    Q_ENUM(SomeEnum)

    enum AnotherEnum { D, E, F };
    Q_ENUM(AnotherEnum)
};

class Message : public QObject
{
    Q_OBJECT
    QML_ELEMENT

    // This would usually cause all enums from OtherType to be registered
    // as members of Message ...
    Q_PROPERTY(OtherType::SomeEnum someEnum READ someEnum CONSTANT)

    // ... but this way it doesn't.
    Q_CLASSINFO("RegisterEnumsFromRelatedTypes", "false")

public:
    OtherType::SomeEnum someEnum() const { return OtherType::B; }
};

La différence importante réside dans la portée des enums en QML. Si une énumération d'une classe apparentée est automatiquement enregistrée, la portée est le type dans lequel elle est importée. Dans le cas ci-dessus, sans l'ajout de Q_CLASSINFO, vous utiliseriez Message.A, par exemple. Si le type C++ contenant les enums est explicitement enregistré et que l'enregistrement des enums des types apparentés est supprimé, le type QML pour le type C++ contenant les enums est la portée de tous ses enums. Vous utiliseriez OtherType.A au lieu de Message.A en QML.

N'oubliez pas que vous pouvez utiliser QML_FOREIGN pour enregistrer un type que vous ne pouvez pas modifier. Vous pouvez également utiliser QML_FOREIGN_NAMESPACE pour enregistrer les énumérateurs d'un type C++ dans un espace de noms QML portant n'importe quel nom en majuscules, même si le même type C++ est également enregistré en tant que type de valeur QML.

Types d'énumération en tant que paramètres de signaux et de méthodes

Les signaux et méthodes C++ avec des paramètres de type énumération peuvent être utilisés à partir de QML à condition que l'énumération et le signal ou la méthode soient tous deux déclarés dans la même classe, ou que la valeur de l'énumération soit l'une de celles déclarées dans le site Qt Namespace.

En outre, si un signal C++ avec un paramètre de type énumération doit pouvoir être connecté à une fonction QML à l'aide de la fonction connect(), le type énumération doit être enregistré à l'aide de qRegisterMetaType().

Pour les signaux QML, les valeurs de l'énumération peuvent être transmises en tant que paramètres du signal à l'aide du type int:

Message {
    signal someOtherSignal(int statusValue)

    Component.onCompleted: {
        someOtherSignal(Message.Loading)
    }
}

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