QML

QML
Paradigmen: deklarativ, reaktiv, Skriptsprache
Erscheinungsjahr: 2009
Entwickler: Qt Project
Aktuelle Version 6.4[1]
Typisierung: stark, dynamisch
Beeinflusst von: JavaScript, Qt
Beeinflusste: Qt
doc.qt.io/qt-5/qmlapplications.html

QML (Qt Modeling Language) ist eine deklarative Programmiersprache, die als Bestandteil von Qt, einer Bibliothek zur Erstellung von Benutzeroberflächen in C++, entwickelt wurde. Zweck der Sprache ist die Entwicklung von Benutzeroberflächen, in erster Linie (jedoch nicht zwangsläufig) für Desktop- und Mobil-Systeme. QML ist syntaktisch an JSON und CSS angelehnt. Durch ihre deklarative Grundstruktur und die nahtlose Einbindung von JavaScript vereint sie deklarative und imperative Ansätze in einer Programmiersprache. QML ist Bestandteil des Qt User Interface Creation Kit (Qt Quick) und kann (inklusive seiner JavaScript-Anteile) durch den Qt Quick Compiler in natives C++ kompiliert werden.[2]

Syntax

Im Zentrum von QML steht die deklarative Beschreibung von GUI-Elementen. Die Beschreibung eines einzelnen Elementes kann beispielsweise so aussehen:

Rectangle {
    color: "green"
    x: 5; y: 10
    width: 50
    height: 2 * width
}

Zu Beginn steht der Typ des Elementes, gefolgt von geschweiften Klammern. In den geschweiften Klammern werden die Eigenschaften des Elements in der Form „Name der Eigenschaft: Wert“ beschrieben. Der Wert kann dabei entweder ein einfaches Literal oder eine vollständige JavaScript-Anweisung, wie im oberen Beispiel bei der Definition der Höhe, sein. Diese Definition mittels einer JavaScript-Anweisung ist jedoch keine Zuweisung nach dem Prinzip imperativer Programmiersprachen, sondern vielmehr eine Definition im mathematischen Sinne. Das heißt im Falle des oberen Beispiels, dass die Höhe immer das Doppelte der Breite ist, auch wenn sich der Wert der Breite ändert. Die tatsächliche Höhe wird dann neu berechnet.

Elemente können geschachtelt werden. Dazu wird die Beschreibung des Kindelements in die Beschreibung des Elternelements hineingeschrieben:

Rectangle {
    //...

    Text {
        id: label
        color: "red"
        text: "Hello World!"
        anchors.centerIn: parent
    }
}

Das Kindelement kann sein Elternelement nun über die Variable parent referenzieren, z. B. um sich über die Eigenschaft („Property“) anchors.centerIn: parent in seinem Elternelement zu zentrieren. Zudem können Elemente prinzipiell, falls definiert, über ihre ID referenziert werden. Die ID wird über die property id definiert.

Ein wichtiger Bestandteil der Sprache ist auch das „Signal-Slot-Prinzip“. Signale werden beispielsweise als Konsequenz von Eingaben ausgelöst, wie z. B. das clicked()-Signal des Elementtyps MouseArea. Auf ein Signal kann reagiert werden, indem man im entsprechenden Element einen „Slot“ definiert, dazu definiert man die Property on<Signalname> mit der auszuführenden JavaScript-Anweisung bzw. dem auszuführenden JavaScript-Block, die bzw. der dann imperativ ausgeführt wird. Für das Beispiel mit der MouseArea könnte das dann wie folgt aussehen:

MouseArea {
    //...
    onClicked: {
        console.log("Hello World");
        label.text = "Guten Abend!";
    }
}

Alternativ kann man Properties und Signale auch selbst definieren oder manuell auslösen:

Item {
    //...
    property bool enabled: true
    signal clicked; // Dies ist die Definition des Signals
    MouseArea {
        anchors.fill: parent
        onClicked: if (enabled) {
            parent.clicked(); // Hiermit wird das Signal ausgelöst
        }
    }
}

Vorteile gegenüber anderen Ansätzen

QWidgets

Traditionell wurden Qt-basierte Oberflächen mithilfe des QWidget-Systems mittels C++ entwickelt. Der Vorteil von QML liegt zum einen in der deklarativen Programmierung, die einen Vorteil in der Übersichtlichkeit des Programmcodes bringt. Vor allem Animationen sind mittels QML leichter umzusetzen. Zum anderen werden QML-Oberflächen ab Version 5.0 von einem OpenGL-basierten Szenengraphen gezeichnet. Dies bringt höhere Ausführungsgeschwindigkeit und verringert die Gefahr von Darstellungsfehlern.

HTML

Im Umfeld von Mobilanwendungen gewinnt HTML zunehmend an Bedeutung. Die bedeutenden Stärken von QML bzw. Qt Quick im Vergleich zu HTML als Grundlage für Benutzeroberflächen sind:

Property-Bindings
Verschiedene Elemente in Benutzeroberflächen sind oft, besonders in Bezug auf die Form, voneinander abhängig, z. B. wenn ein Element eine variable Breite hat, ein Geschwisterelement jedoch stets den restlichen verbleibenden horizontalen Platz im Elternelement nutzen soll. Was in HTML mit CSS wenn überhaupt nur über Tricks möglich ist, ist in QML mit der einfachen Property-Definition „width: parent.width - otherElement.width“ möglich.
Positionierungen
Die Positionierung von Elementen ist in QtQuick über drei verschiedene Wege möglich: Absolute Positionierung, bezogen auf das Elternelement, Layouts und sogenannte Anker. Während Layouts bereits etwas sind, das es in HTML in dieser Form nicht gibt, wodurch Layouts für sich schon eine Stärke von QML sind, kommt bei Ankern die Mächtigkeit von QML erst richtig zum Tragen. Jedes grafische QML-Element besitzt mehrere Anker, nämlich top, bottom, left, right, verticalCenter und horizontalCenter. Jedem dieser Anker kann als Wert ein beliebiger Anker eines anderen Elementes per Property-Binding zugewiesen werden (horizontale Anker natürlich nur anderen horizontalen Ankern, vertikale Anker nur anderen vertikalen Ankern). So kann z. B. die Mitte eines Elementes an der rechten Kante eines anderen Objektes vertikal zentral ausgerichtet werden:
Das Ergebnis
Rectangle {
    id: rect1
    color: "green"
    width: 100
    height: 100
}

Rectangle {
    id: rect2
    color: "red"
    width: 20
    height: 20
    anchors.horizontalCenter: rect1.right
    anchors.verticalCenter: rect1.verticalCenter
}
Objektorientierung
Neben den Standard-Elementtypen ist es in QML möglich, eigene Elementtypen, sog. Komponenten, zu definieren. Dies funktioniert, indem man eine gewöhnliche QML-Datei mit dem Namen der Komponente erstellt und in einer anderen QML-Datei einfach ein Element mit dem Namen der Komponente als Elementtyp erstellt (die Dateien müssen im selben Verzeichnis liegen). Das Element ist jetzt programmtechnisch transparent eine Instanz des Codes, der in der entsprechenden Komponenten-QML-Datei steht. Dadurch können nach dem Prinzip der Objektorientierung mehrfach verwendete Code-Segmente ausgelagert und wiederverwendet werden. Für komplexere Anwendungsfälle ist es außerdem möglich, in C++ entwickelte, eigene Funktionalitäten mit QML zu verknüpfen. So können einem QML-Kontext beispielsweise beliebige QObject-Instanzen zugewiesen werden, auf deren Attribute und Methoden dann im QML-Code zugegriffen werden kann. Durch das Signal-Slot-Konzept, welches in der gesamten Qt-Bibliothek verwendet wird, können QML-Attributwerte auch an C++-Attributwerte gebunden und bei deren Änderung automatisch aktualisiert werden. Zudem kann man eigene QML-Elementtypen mit beliebiger Funktionalität in C++ entwickeln oder bestehende QML-Elemente erweitern. Für visuelle Elemente stehen dabei sowohl die bereits für QWidgets verwendeten Zeichenroutinen als auch der neuere, OpenGL-basierte Szenengraph zur Verfügung.

Der wichtigste Vorteil von HTML ist die größere Verbreitung und größere Bekanntheit der Sprache.

Einzelnachweise

  1. Volker Hilsheimer: Qt 6.4 Released. 29. September 2022.
  2. Rainald Menge-Sonnentag: Cross-Plattform-Framework Qt 6.3 kompiliert QML nach C++. In: heise.de. Abgerufen am 5. Januar 2023.