Sur cette page

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

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

Le moteur Qml prend en charge de manière native un grand nombre de types de données Qt C++. De plus, il est possible d'enregistrer des types C++ personnalisés dans le système de types Qml afin de les rendre accessibles au moteur.

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

Cette page présente les types de données pris en charge par le moteur QML et explique comment ils sont convertis entre QML et C++.

Propriété des données

Lorsque des données sont transférées du C++ vers le QML, la propriété de ces données reste toujours du côté du C++. La seule exception à cette règle concerne le cas où une instance de ` QObject ` est renvoyée par un appel explicite à une méthode C++ : dans ce cas, le moteur QML prend possession de l'objet, à moins que la propriété de l'objet n'ait été explicitement définie pour rester entre les mains du C++ en appelant ` QQmlEngine::setObjectOwnership()` avec `QQmlEngine::CppOwnership` spécifié.

De plus, le moteur QML respecte la sémantique normale de propriété parentale des objets Qt C++ dans le cadre de QObject, et ne supprimera jamais une instance de ` QObject ` qui possède un parent.

Types de données de base de Qt

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 du C++ vers le Qml et inversement :

Remarque : les classes fournies par le Qt GUI module, telles que QColor, QFont, QQuaternion et QMatrix4x4, ne sont disponibles depuis QML que lorsque le Qt Quick module est inclus.

Pour plus de commodité, bon nombre de ces types peuvent être spécifiés en QML à l'aide de valeurs de chaîne de caractères, ou via une méthode associée 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 de caractères au format « widthxheight », ou par la fonction Qt.size():

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

Pour plus d’informations, consultez la documentation relative à chaque type dans la section « Types de valeurs QML ».

Types dérivés de QObject

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

Le moteur permet l'enregistrement de types instanciables et non instanciables. Une fois qu'une classe est enregistrée en tant que type QML, elle peut être utilisée comme type de données pour l'échange de données entre QML et C++. Voir Enregistrement de types C++ auprès du 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 intègre une prise en charge native de la conversion d’un certain nombre de types Qt en types JavaScript correspondants, et inversement, lors du transfert de données entre Qml et C++. Cela permet d’utiliser ces types et de les recevoir en C++ ou en JavaScript sans avoir à implémenter de types personnalisés donnant accès aux valeurs des données et à leurs attributs.

(Notez que l’environnement JavaScript dans QML modifie les prototypes d’objets JavaScript natifs, notamment ceux de String, Date et Number, afin d’offrir des fonctionnalités supplémentaires. Pour plus de détails, consultez la section Environnement hôte JavaScript.)

QVariantList et QVariantMap vers des structures de type tableau et objet JavaScript

Le moteur QML assure une conversion automatique de type entre les objets ` QVariantList ` et les structures de type « tableau » en JavaScript, ainsi qu’entre les objets ` QVariantMap ` et les objets JavaScript.

Un « array-like », selon la terminologie ECMAScript, est un objet utilisé comme un tableau. Les « array-likes » générés par la conversion à partir de ` QVariantList ` (et d’autres conteneurs séquentiels C++) ne se limitent pas à cela : ils offrent également les méthodes courantes des tableaux et synchronisent automatiquement la propriété `length`. Ils peuvent être utilisés exactement comme des tableaux JavaScript à toutes fins pratiques. La méthode ` Array.isArray()` renvoie toutefois toujours `false` pour ces objets.

Par exemple, la fonction définie ci-dessous en QML attend deux arguments, un tableau et un objet, et affiche leur contenu en utilisant la syntaxe JavaScript standard pour accéder aux éléments d’un tableau et d’un objet. Le code C++ ci-dessous appelle cette fonction en lui passant un ` QVariantList ` et un ` QVariantMap`, qui sont automatiquement convertis respectivement en valeurs de type « tableau-like » et en valeurs d’objet JavaScript :

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)));

Cela produit une sortie du type :

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 sous forme de tableau ou d’objet JavaScript dans QML, et est automatiquement convertie en « QVariantList » ou « QVariantMap » lorsqu’elle est transmise au C++.

Depuis Qt 6.5, les propriétés QVariantList de types C++ peuvent être modifiées in situ par du code QML. Depuis Qt 6.9, les propriétés QVariantMap de types C++ peuvent être modifiées in situ par du code QML.

QDateTime vers Date JavaScript

Le moteur QML assure la conversion automatique entre les valeurs de type ` QDateTime ` et les objets ` Date ` de JavaScript.

Par exemple, la fonction définie ci-dessous en QML attend un objet JavaScript ` Date ` et renvoie également un nouvel objet ` Date ` contenant la date et l’heure actuelles. Le code C++ ci-dessous appelle cette fonction en lui 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 une valeur ` QDateTime ` lorsqu’il est reçu en 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;
QML
// MyItem.qml
Item {
    function readDate(dt) {
        console.log("The given date is:", dt.toUTCString());
        return new Date();
    }
}
 
C++

De même, si un type C++ utilise une expression « QDateTime » pour un type de propriété ou un paramètre de méthode, la valeur peut être créée sous la forme d’un objet JavaScript « Date » dans QML, puis est automatiquement convertie en une valeur « QDateTime » lorsqu’elle est transmise au C++.

Remarque : attention à la différence de numérotation des mois : en JavaScript, janvier correspond à 0 et décembre à 11, soit un écart d’une unité par rapport à la numérotation de Qt, où janvier correspond à 1 et décembre à 12.

Remarque : lorsque vous utilisez une chaîne de caractères en JavaScript comme valeur d’un objet ` Date `, notez qu’une chaîne ne comportant aucun champ d’heure (c’est-à-dire une simple date) est interprétée comme le début de la journée en UTC, contrairement à ` new Date(y, m, d) ` qui utilise le début de la journée en heure locale. La plupart des autres façons de construire un objet ` Date ` en JavaScript produisent une heure locale, à moins d’utiliser des méthodes dont le nom comporte « UTC ». Si votre programme s’exécute dans un fuseau horaire en retard par rapport à l’UTC (théoriquement à l’ouest du méridien de Greenwich), l’utilisation d’une chaîne de caractères contenant uniquement la date donnera lieu à un objet ` Date ` dont la valeur de ` getDate() ` est inférieure d’une unité au numéro du jour indiqué dans votre chaîne ; la valeur de ` getHours()` sera généralement très élevée. Les variantes UTC de ces méthodes, getUTCDate() et getUTCHours(), donneront les résultats attendus pour de tels objets Date. Voir également la section suivante.

QDate et Date JavaScript

Le moteur QML effectue automatiquement la conversion entre ` QDate ` et le type JavaScript ` Date ` en représentant la date par le début UTC de son jour. Une date est reconvertie en ` QDate ` via ` QDateTime`, en sélectionnant sa méthode ` date()`, en utilisant le format heure locale de la date, sauf si le format UTC de celle-ci coïncide avec le début du jour suivant, auquel cas le format UTC est utilisé.

Cette approche quelque peu atypique est une solution de contournement au fait que la construction par JavaScript d’un objet ` Date ` à partir d’une chaîne de caractères contenant uniquement une date utilise le début de la journée en UTC, tandis que ` new Date(y, m, d) ` utilise le début de la date indiquée en heure locale, comme expliqué dans une note à la fin de la section précédente.

Par conséquent, lorsqu’une propriété ou un paramètre de type ` QDate ` est exposé à QML, il convient de faire preuve de prudence 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 dont le nom ne comporte pas la mention « UTC ».

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

QTime et la date JavaScript

Le moteur QML assure une conversion automatique des valeurs ` QTime ` en objets ` Date ` de JavaScript. Les valeurs ` QTime ` ne contenant pas de composante de date, celle-ci est créée uniquement pour les besoins de la conversion. Par conséquent, vous ne devez pas vous fier à la composante de date de l’objet `Date` résultant.

En arrière-plan, la conversion d’un objet JavaScript ` Date ` en ` QTime ` s’effectue en le convertissant d’abord en objet ` QDateTime ` (en utilisant l’heure locale), puis en appelant sa méthode ` time()`.

Type de séquence vers tableau JavaScript

Consultez la section « Types de séquence QML » pour une description générale des types de séquence. L'QtQml module contient quelques types de séquence que vous pourriez souhaiter utiliser.

Vous pouvez également créer une structure de données de type liste en construisant un tableau JavaScript ( QJSValue ) à l'aide de la fonction ` QJSEngine::newArray()`. Un tel tableau JavaScript ne nécessite aucune conversion lors de son transfert entre QML et C++. Consultez la page QJSValue#Working With Arrays pour plus de détails sur la manière de manipuler des tableaux JavaScript depuis C++.

QByteArray vers ArrayBuffer JavaScript

Le moteur QML assure la conversion automatique de type entre les valeurs de ` QByteArray ` et les objets ` ArrayBuffer ` de JavaScript.

Types de valeurs

Certains types de valeurs dans Qt, tels que ` QPoint `, sont représentés en JavaScript sous forme d’objets possédant les mêmes propriétés et fonctions que dans l’API C++. La même représentation est possible avec des types de valeurs C++ personnalisés. Pour activer un type de valeur personnalisé avec le moteur QML, la déclaration de 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 les propriétés suivantes :

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)

La pratique courante consiste à utiliser une classe de gadget comme type d’une propriété, ou à émettre un gadget en tant qu’argument de signal. Dans ces cas-là, l’instance du gadget est transmise par valeur entre le C++ et le 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 setter de la propriété C++. Dans Qt 5, les types de gadgets ne peuvent pas être instanciés par déclaration directe en QML. En revanche, une instance de ` QObject ` peut être déclarée ; et les instances de ` QObject ` sont toujours transmises par pointeur du C++ vers le 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()` afin de l’enregistrer dans le système de méta-objets de Qt. Par exemple, la classe ` Message ` ci-dessous comporte 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();
};

À condition que la classe ` Message ` ait été enregistrée auprès du système de types QML, son énumération ` Status ` peut être utilisée depuis QML :

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

Pour utiliser une énumération comme type d’ flags s dans QML, consultez la fonction Q_FLAG().

Remarque : les noms des valeurs de l'énumération doivent commencer par une majuscule pour être accessibles depuis le QML.

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

Les classes d'énumération sont enregistrées dans QML sous forme de propriétés avec ou sans portée. La valeur de l'Ready sera enregistrée sous les noms Message.Status.Ready et Message.Ready.

Lors de l'utilisation de classes d'énumération, il peut exister plusieurs énumérations utilisant les mêmes identifiants. L'enregistrement sans portée sera écrasé par la dernière énumération enregistrée. Pour les classes présentant de tels conflits de noms, il est possible de désactiver l'enregistrement sans portée en annotant votre classe avec une macro spéciale Q_CLASSINFO. Utilisez le nom RegisterEnumClassesUnscoped avec la valeur false pour empêcher que les énumérations avec portée ne soient fusionnées 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 énumérations issues de types associés sont généralement enregistrées dans la portée du type associé. Par exemple, toute énumération provenant d’un type différent et utilisée dans une déclaration ` Q_PROPERTY ` entraîne la mise à disposition de toutes les énumérations de ce type dans QML. Cela constitue généralement davantage un inconvénient qu’une fonctionnalité. Pour éviter cela, annotez votre classe à l’aide d’une macro spéciale « Q_CLASSINFO ». Utilisez le nom « RegisterEnumsFromRelatedTypes » avec la valeur « false » pour empêcher les énumérations de types associés d’être enregistrées dans ce type.

Vous devez enregistrer explicitement les types parents de toutes les énumérations que vous souhaitez utiliser en QML, à l’aide de ` QML_ELEMENT ` ou ` QML_NAMED_ELEMENT`, plutôt que de compter sur l’injection de leurs énumérations 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 énumérations en QML. Si une énumération provenant d’une classe associée est automatiquement enregistrée, sa portée correspond au type dans lequel elle est importée. Dans le cas ci-dessus, sans l’ Q_CLASSINFO supplémentaire, vous utiliseriez par exemple Message.A. Si le type C++ contenant les énumérations est explicitement enregistré et que l’enregistrement des énumérations provenant de types associés est supprimé, le type QML correspondant au type C++ contenant les énumérations constitue la portée de toutes ses énumérations. Vous utiliseriez alors OtherType.A au lieu de Message.A en QML.

Notez 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 dont le nom est entièrement en majuscules, même si ce même type C++ est également enregistré en tant que type de valeur QML.

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

Les signaux et méthodes C++ comportant des paramètres de type énumération peuvent être utilisés depuis QML à condition que l’énumération et le signal ou la méthode soient tous deux déclarés au sein de la même classe, ou que la valeur d’énumération fasse partie de celles déclarées dans ` Qt Namespace`.

De plus, 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 d'énumération doit être enregistré à l'aide de qRegisterMetaType().

Pour les signaux QML, les valeurs d'énumération peuvent être transmises en tant que paramètres de 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.