Auf dieser Seite

Datentypkonvertierung zwischen QML und C++

Wenn Datenwerte zwischen QML und C++ ausgetauscht werden, werden sie von der QML-Engine so konvertiert, dass sie die richtigen Datentypen aufweisen, die für die Verwendung in QML bzw. C++ geeignet sind. Dies setzt voraus, dass die ausgetauschten Daten einen Typ haben, der von der Engine erkannt werden kann.

Die Qml-Engine bietet integrierte Unterstützung für eine Vielzahl von Qt-C++-Datentypen. Darüber hinaus können benutzerdefinierte C++-Typen im Qml-Typensystem registriert werden, um sie der Engine zur Verfügung zu stellen.

Weitere Informationen zu C++ und den verschiedenen Methoden zur QML-Integration finden Sie auf der Übersichtsseite zur C++- und QML-Integration.

Auf dieser Seite werden die von der QML-Engine unterstützten Datentypen sowie deren Konvertierung zwischen QML und C++ erläutert.

Dateneigentum

Wenn Daten von C++ nach QML übertragen werden, verbleibt die Eigentümerschaft an den Daten stets bei C++. Eine Ausnahme von dieser Regel bildet der Fall, dass ein ` QObject ` von einem expliziten C++-Methodenaufruf zurückgegeben wird: In diesem Fall übernimmt die QML-Engine die Eigentumsrechte an dem Objekt, es sei denn, es wurde durch den Aufruf von ` QQmlEngine::setObjectOwnership()` mit der Angabe von `QQmlEngine::CppOwnership` explizit festgelegt, dass die Eigentumsrechte bei C++ verbleiben.

Darüber hinaus berücksichtigt die QML-Engine die normale Semantik der „ QObject “-Eltern-Eigentümerschaft von Qt-C++-Objekten und löscht niemals eine „ QObject “-Instanz, die einen Elternteil hat.

Grundlegende Qt-Datentypen

Standardmäßig erkennt QML die folgenden Qt-Datentypen, die bei der Übergabe von C++ nach QML und umgekehrt automatisch in einen entsprechenden QML-Werttyp konvertiert werden:

Hinweis: Vom Modul bereitgestellte Klassen Qt GUI Modul bereitgestellten Klassen, wie z. B. ` QColor`, ` QFont`, ` QQuaternion ` und ` QMatrix4x4`, sind in QML nur verfügbar, wenn das Qt Quick Modul eingebunden ist.

Der Einfachheit halber können viele dieser Typen in QML durch Zeichenfolgenwerte oder durch eine entsprechende Methode des Objekts ` QtQml::Qt ` angegeben werden. Beispielsweise ist die Eigenschaft ` Image::sourceSize ` vom Typ ` size ` (der automatisch in den Typ ` QSize ` umgewandelt wird) und kann durch einen Zeichenfolgenwert im Format „BreitexHöhe“ oder durch die Qt-Funktion `size() ` angegeben werden:

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

Weitere Informationen finden Sie in der Dokumentation zu den einzelnen Typen unter „QML-Werttypen “.

Von QObject abgeleitete Typen

Jede von ` QObject` abgeleitete Klasse kann als Typ für den Datenaustausch zwischen QML und C++ verwendet werden, sofern die Klasse im QML-Typensystem registriert wurde.

Die Engine ermöglicht die Registrierung sowohl instanziierbarer als auch nicht instanziierbarer Typen. Sobald eine Klasse als QML-Typ registriert ist, kann sie als Datentyp für den Datenaustausch zwischen QML und C++ verwendet werden. Weitere Details zur Typregistrierung finden Sie unter „Registrieren von C++-Typen im QML-Typsystem “.

Konvertierung zwischen Qt- und JavaScript-Typen

Die Qml-Engine bietet integrierte Unterstützung für die Konvertierung einer Reihe von Qt-Typen in entsprechende JavaScript-Typen und umgekehrt, wenn Daten zwischen Qml und C++ übertragen werden. Dadurch ist es möglich, diese Typen zu verwenden und sie in C++ oder JavaScript zu empfangen, ohne benutzerdefinierte Typen implementieren zu müssen, die Zugriff auf die Datenwerte und deren Attribute bieten.

(Beachten Sie, dass die JavaScript-Umgebung in QML native JavaScript-Objektprototypen, darunter die von String, Date und Number, modifiziert, um zusätzliche Funktionen bereitzustellen. Weitere Details finden Sie unter „JavaScript-Host-Umgebung “.)

QVariantList und QVariantMap als Array-ähnliche Strukturen und Objekte in JavaScript

Die QML-Engine bietet eine automatische Typkonvertierung zwischen ` QVariantList ` und JavaScript-arrayähnlichen Strukturen sowie zwischen ` QVariantMap ` und JavaScript-Objekten.

Ein Array-ähnliches Objekt ist im Sinne von ECMAScript ein Objekt, das wie ein Array verwendet wird. Die durch die Konvertierung von „ QVariantList “ (und anderen sequenziellen C++-Containern) erzeugten Array-ähnlichen Objekte sind nicht nur das, sondern bieten auch die gängigen Array-Methoden und synchronisieren automatisch die „length“-Eigenschaft. Sie können für alle praktischen Zwecke genau wie JavaScript-Arrays verwendet werden. Die Methode `Array.isArray()` gibt für sie jedoch weiterhin „false“ zurück.

Beispielsweise erwartet die unten in QML definierte Funktion zwei Argumente – ein Array und ein Objekt – und gibt deren Inhalt unter Verwendung der Standard-JavaScript-Syntax für den Zugriff auf Array- und Objektelemente aus. Der folgende C++-Code ruft diese Funktion auf und übergibt dabei ein ` QVariantList ` sowie ein ` QVariantMap`, die automatisch in array-ähnliche Werte bzw. Objektwerte in JavaScript konvertiert werden:

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

Dies erzeugt eine Ausgabe wie:

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)

Ähnlich verhält es sich, wenn ein C++-Typ einen Typ vom Typ „ QVariantList “ oder „ QVariantMap “ für einen Eigenschaftstyp oder einen Methodenparameter verwendet: Der Wert kann in QML als JavaScript-Array oder -Objekt erstellt werden und wird automatisch in einen „ QVariantList “ oder „ QVariantMap “ konvertiert, wenn er an C++ übergeben wird.

Seit Qt 6.5 können „ QVariantList “-Eigenschaften von C++-Typen durch QML-Code direkt geändert werden. Seit Qt 6.9 können „ QVariantMap “-Eigenschaften von C++-Typen durch QML-Code direkt geändert werden.

QDateTime zu JavaScript-Datum

Die QML-Engine bietet eine automatische Typkonvertierung zwischen „ QDateTime “-Werten und JavaScript-Objekten vom Typ „ Date “.

Beispielsweise erwartet die unten in QML definierte Funktion ein JavaScript-Objekt vom Typ „ Date “ und gibt zudem ein neues „ Date “-Objekt mit dem aktuellen Datum und der aktuellen Uhrzeit zurück. Der folgende C++-Code ruft diese Funktion auf und übergibt einen ` QDateTime `-Wert, der von der Engine automatisch in ein ` Date `-Objekt konvertiert wird, wenn er an die Funktion ` readDate() ` übergeben wird. Im Gegenzug gibt die Funktion `readDate()` ein ` Date `-Objekt zurück, das automatisch in einen ` QDateTime `-Wert konvertiert wird, wenn es in C++ empfangen wird:

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;

Ebenso gilt: Wenn ein C++-Typ einen „ QDateTime “ als Eigenschaftstyp oder Methodenparameter verwendet, kann der Wert in QML als JavaScript-Objekt vom Typ „ Date “ erstellt werden und wird automatisch in einen Wert vom Typ „ QDateTime “ konvertiert, wenn er an C++ übergeben wird.

Hinweis: Achten Sie auf den Unterschied bei der Monatsnummerierung: In JavaScript wird der Januar als 0 und der Dezember als 11 nummeriert, was eine Abweichung um eins gegenüber der Qt-Nummerierung darstellt, bei der der Januar als 1 und der Dezember als 12 nummeriert wird.

Hinweis: Wenn Sie in JavaScript eine Zeichenkette als Wert für ein ` Date `-Objekt verwenden, beachten Sie, dass eine Zeichenkette ohne Zeitfelder (also ein einfaches Datum) als UTC-Beginn des betreffenden Tages interpretiert wird, im Gegensatz zu ` new Date(y, m, d) `, das den Beginn des Tages in Ortszeit verwendet. Die meisten anderen Möglichkeiten, ein ` Date `-Objekt in JavaScript zu erstellen, ergeben eine Ortszeit, es sei denn, es werden Methoden verwendet, deren Namen „UTC“ enthalten. Wenn Ihr Programm in einer Zeitzone hinter UTC (nominal westlich des Nullmeridians) ausgeführt wird, führt die Verwendung einer reinen Datumszeichenfolge zu einem „ Date “-Objekt, dessen „ getDate() “ um eins kleiner ist als die Tageszahl in Ihrer Zeichenfolge; es weist typischerweise einen großen Wert für „ getHours() “ auf. Die UTC-Varianten dieser Methoden, getUTCDate() und getUTCHours(), liefern die Ergebnisse, die Sie für solche „ Date “-Objekte erwarten. Siehe auch den nächsten Abschnitt.

QDate und JavaScript-Date

Die QML-Engine konvertiert automatisch zwischen „ QDate “ und dem JavaScript-Typ „ Date “, indem sie das Datum anhand des UTC-Beginns des jeweiligen Tages darstellt. Ein Datum wird über „ QDateTime “ wieder auf „ QDate “ abgebildet, wobei die Methode „ date()“ ausgewählt wird und die Ortszeitform des Datums verwendet wird, es sei denn, die UTC-Form stimmt mit dem Beginn des nächsten Tages überein; in diesem Fall wird die UTC-Form verwendet.

Diese etwas eigenwillige Vorgehensweise ist eine Umgehungslösung für die Tatsache, dass die Erstellung eines ` Date `-Objekts aus einer reinen Datumszeichenfolge in JavaScript den UTC-Beginn des Tages verwendet, während ` new Date(y, m, d) ` den Beginn des angegebenen Datums in Ortszeit verwendet, wie in einem Hinweis am Ende des vorherigen Abschnitts erläutert.

Daher ist bei der Bereitstellung einer „ QDate “-Eigenschaft oder eines Parameters für QML beim Auslesen ihres Werts Vorsicht geboten: Die Methoden „ Date.getUTCFullYear() “, „ Date.getUTCMonth() “ und „ Date.getUTCDate() “ liefern mit größerer Wahrscheinlichkeit die von den Benutzern erwarteten Ergebnisse als die entsprechenden Methoden, deren Namen kein „UTC“ enthalten.

Daher ist es in der Regel robuster, eine „ QDateTime “-Eigenschaft zu verwenden. Dies ermöglicht es, auf der „ QDateTime “-Seite zu steuern, ob das Datum (und die Uhrzeit) in UTC oder in Ortszeit angegeben wird; solange der JavaScript-Code so geschrieben ist, dass er mit demselben Standard arbeitet, sollten Probleme vermieden werden können.

QTime und JavaScript-Datum

Die QML-Engine bietet eine automatische Typkonvertierung von „ QTime “-Werten in JavaScript- Date -Objekte. Da „ QTime “-Werte keine Datumsangabe enthalten, wird diese ausschließlich für die Konvertierung erstellt. Sie sollten sich daher nicht auf die Datumsangabe des resultierenden „Date“-Objekts verlassen.

Im Hintergrund erfolgt die Konvertierung von einem JavaScript- Date -Objekt in ein QTime durch die Umwandlung in ein QDateTime -Objekt (unter Verwendung der Ortszeit) und den Aufruf der Methode ` time()`.

Sequenztyp in JavaScript-Array

Eine allgemeine Beschreibung von Sequenztypen finden Sie unter „QML-Sequenztypen “. Das „ QtQml module “ enthält einige Sequenztypen, die Sie möglicherweise verwenden möchten.

Sie können auch eine listenähnliche Datenstruktur erstellen, indem Sie mit ` QJSEngine::newArray()` ein ` QJSValue ` bilden. Ein solches JavaScript-Array benötigt keine Konvertierung, wenn es zwischen QML und C++ übergeben wird. Unter „ QJSValue#Working With Arrays “ finden Sie Details dazu, wie Sie JavaScript-Arrays aus C++ heraus bearbeiten können.

QByteArray in JavaScript-ArrayBuffer

Die QML-Engine bietet eine automatische Typkonvertierung zwischen ` QByteArray `-Werten und JavaScript-` ArrayBuffer `-Objekten.

Werttypen

Einige Werttypen in Qt, wie beispielsweise „ QPoint “, werden in JavaScript als Objekte dargestellt, die dieselben Eigenschaften und Funktionen wie in der C++-API aufweisen. Die gleiche Darstellung ist auch für benutzerdefinierte C++-Werttypen möglich. Um einen benutzerdefinierten Werttyp in der QML-Engine zu aktivieren, muss die Klassendeklaration mit ` Q_GADGET` gekennzeichnet werden. Eigenschaften, die in der JavaScript-Darstellung sichtbar sein sollen, müssen mit ` Q_PROPERTY` deklariert werden. Ebenso müssen Funktionen mit ` Q_INVOKABLE` gekennzeichnet werden. Dies gilt auch für C++-APIs auf Basis von „ QObject “. Die unten stehende Klasse ` Actor ` ist beispielsweise als „Gadget“ gekennzeichnet und verfügt über folgende Eigenschaften:

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)

Das übliche Muster besteht darin, eine Gadget-Klasse als Typ einer Eigenschaft zu verwenden oder ein Gadget als Signalargument auszugeben. In solchen Fällen wird die Gadget-Instanz zwischen C++ und QML als Wert übergeben (da es sich um einen Werttyp handelt). Wenn QML-Code eine Eigenschaft eines Gadgets ändert, wird das gesamte Gadget neu erstellt und an den C++-Eigenschaftssetter zurückgegeben. In Qt 5 können Gadget-Typen nicht durch direkte Deklaration in QML instanziiert werden. Im Gegensatz dazu kann eine Instanz von ` QObject ` deklariert werden; und Instanzen von ` QObject ` werden immer per Zeiger von C++ an QML übergeben.

Aufzählungstypen

Um eine benutzerdefinierte Aufzählung als Datentyp zu verwenden, muss ihre Klasse registriert werden, und die Aufzählung muss zudem mit ` Q_ENUM()` deklariert werden, um sie im Metobjektsystem von Qt zu registrieren. Die folgende ` Message `-Klasse enthält beispielsweise die Aufzählung ` 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();
};

Sofern die Klasse ` Message ` im QML-Typensystem registriert wurde, kann ihre Enumeration ` Status ` aus QML heraus verwendet werden:

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

Informationen zur Verwendung einer Enumeration als „ flags “-Typ in QML finden Sie unter „ Q_FLAG()“.

Hinweis: Die Namen der Enum-Werte müssen mit einem Großbuchstaben beginnen, damit sie von QML aus zugänglich sind.

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

Enum-Klassen werden in QML als Eigenschaften mit und ohne Gültigkeitsbereich registriert. Der Wert „ Ready “ wird als „ Message.Status.Ready “ und „ Message.Ready “ registriert.

Bei der Verwendung von Enum-Klassen kann es vorkommen, dass mehrere Enums dieselben Bezeichner verwenden. Die Registrierung ohne Gültigkeitsbereich wird durch die zuletzt registrierte Enumeration überschrieben. Bei Klassen, die solche Namenskonflikte enthalten, ist es möglich, die Registrierung ohne Gültigkeitsbereich zu deaktivieren, indem Sie Ihre Klasse mit einem speziellen „ Q_CLASSINFO “-Makro versehen. Verwenden Sie den Namen „ RegisterEnumClassesUnscoped “ mit dem Wert „ false “, um zu verhindern, dass Enumerationen mit Gültigkeitsbereich in denselben Namensraum zusammengeführt werden.

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

Enums aus verwandten Typen werden in der Regel im Geltungsbereich des jeweiligen Typs registriert. Beispielsweise führt die Verwendung eines Enums aus einem anderen Typ in einer ` Q_PROPERTY `-Deklaration dazu, dass alle Enums dieses Typs in QML verfügbar sind. Dies ist in der Regel eher ein Nachteil als ein Vorteil. Um dies zu verhindern, versehen Sie Ihre Klasse mit einem speziellen Makro namens „ Q_CLASSINFO “. Verwenden Sie den Namen „ RegisterEnumsFromRelatedTypes “ mit dem Wert „ false “, um zu verhindern, dass Enums aus verwandten Typen in diesem Typ registriert werden.

Sie sollten die übergeordneten Typen aller Enums, die Sie in QML verwenden möchten, explizit mit „ QML_ELEMENT “ oder „ QML_NAMED_ELEMENT “ registrieren, anstatt sich darauf zu verlassen, dass deren Enums in andere Typen injiziert werden.

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

Der wichtige Unterschied besteht im Geltungsbereich der Enums in QML. Wenn ein Enum aus einer verwandten Klasse automatisch registriert wird, ist der Geltungsbereich der Typ, in den es importiert wird. Im oben genannten Fall würden Sie beispielsweise ohne das zusätzliche ` Q_CLASSINFO` ` Message.A` verwenden. Wenn der C++-Typ, der die Enums enthält, explizit registriert wird und die Registrierung von Enums aus verwandten Typen unterdrückt wird, ist der QML-Typ für den C++-Typ, der die Enums enthält, der Geltungsbereich für alle seine Enums. In QML würden Sie dann „ OtherType.A “ anstelle von „ Message.A “ verwenden.

Beachten Sie, dass Sie mit „ QML_FOREIGN “ einen Typ registrieren können, den Sie nicht ändern können. Sie können außerdem mit „ QML_FOREIGN_NAMESPACE “ die Enumeratoren eines C++-Typs in einem QML-Namensraum mit einem beliebigen Namen in Großbuchstaben registrieren, selbst wenn derselbe C++-Typ auch als QML-Werttyp registriert ist.

Aufzählungstypen als Signal- und Methodenparameter

C++-Signale und -Methoden mit Parametern vom Typ einer Aufzählung können in QML verwendet werden, sofern sowohl die Aufzählung als auch das Signal oder die Methode innerhalb derselben Klasse deklariert sind oder der Aufzählungswert zu den in der ` Qt Namespace` deklarierten Werten gehört.

Soll ein C++-Signal mit einem Enumerationsparameter über die Funktion `connect() ` mit einer QML-Funktion verbunden werden können, muss der Enumerationstyp zusätzlich mit ` qRegisterMetaType()` registriert werden.

Bei QML-Signalen können Enum-Werte mithilfe des Typs ` int ` als Signalparameter übergeben werden:

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.