Skip to content
Zurück zum Blog
· 6 Min. Lesezeit

Qt als zentraler Bestandteil für Multiplattformumgebungen

Eine Codebasis für Embedded, Desktop und Mobile: Wie Qt mit konsequenter Trennung von Logik und UI echte Multiplattform-Produkte ermöglicht.

Diagramm einer Qt-Codebasis — ein gemeinsamer C++-Kern und eine QML-UI mit gekapselter Plattformschicht — die per CMake für Embedded Linux, Desktop und Mobile gebaut wird.

Kurz gesagt: Mit Qt schreiben Sie die Geschäftslogik einmal in plattformunabhängigem C++ und liefern sie über anpassbare QML-Oberflächen auf Desktop, Embedded und Mobile aus – eine Codebasis, viele Formfaktoren.

Viele Produkte existieren heute nicht mehr als einzelnes Gerät, sondern als Ökosystem: das eingebettete Gerät selbst, eine Desktop-Anwendung zur Konfiguration, eine mobile App zur Fernüberwachung. Drei Plattformen getrennt zu entwickeln bedeutet dreifachen Aufwand – und dreifache Gelegenheit, dass die Varianten auseinanderlaufen. Qt bietet hier einen überzeugenden Mittelweg: dieselbe C++/QML-Basis läuft überall, ohne zum kleinsten gemeinsamen Nenner zu werden.

Eine Codebasis, mehrere Formfaktoren

Der Kern der Idee ist, das Produkt einmal zu bauen und nur die Oberfläche pro Gerät zu variieren. Praktisch teilt man das Projekt in zwei Schichten: einen plattformunabhängigen Kern aus C++-Bibliotheken (Geräteprotokolle, Zustandsautomaten, Datenmodelle, Telemetrie) und eine dünne, austauschbare Präsentationsschicht aus QML. Der Kern kennt weder Bildschirmgröße noch Eingabemethode – er stellt lediglich Modelle und Kommandos bereit. Ob diese auf einem 7-Zoll-Touchpanel an einer Maschine, in einem skalierbaren Desktop-Fenster oder auf einem Smartphone gerendert werden, entscheidet allein die QML-Ebene.

Diese Trennung ist mehr als Ordnungsliebe. Sie legt fest, was geteilt wird (die risikoreiche, teuer zu testende Logik) und was pro Formfaktor divergieren darf (Layout, Navigation, Interaktionsmuster). Damit vermeiden Sie die klassische Falle von Multiplattform-Projekten: dass sich Sonderfälle für einzelne Geräte tief in den gemeinsamen Code fressen. Wie sich diese Architektur auf robuste C++-Kerne stützt, betrachten wir in unserer C++-Entwicklung im Detail.

Wie Qt die Plattform abstrahiert

Der Grund, warum eine Codebasis überhaupt tragfähig ist, liegt in Qts durchgängigen Abstraktionsschichten. Statt gegen native APIs zu programmieren, arbeiten Sie gegen eine stabile Qt-API, die das Betriebssystem darunter kapselt:

  • Qt Platform Abstraction (QPA): Fenster, Eingabe und Grafikkontext werden über austauschbare Plugins bereitgestellt – eglfs oder Wayland auf Embedded Linux, xcb auf Desktop-Linux, Cocoa auf macOS, die jeweiligen nativen Backends auf Windows, Android und iOS.
  • RHI (Rendering Hardware Interface): Qt 6 rendert über eine Grafikabstraktion, die je nach Ziel auf Vulkan, Metal, Direct 3D oder OpenGL abbildet. Dasselbe QML läuft damit auf einer GPU im Industrie-Gateway wie auf einem Desktop.
  • Einheitliche Systemdienste: Dateizugriff, Netzwerk, Threads, Serialisierung und Zeit sind plattformübergreifend identisch – kein #ifdef-Dickicht für Alltagsaufgaben.

Auf Embedded Linux ist genau diese QPA-Schicht der Berührungspunkt zum Board Support Package. Wie ein schlankes, reproduzierbares Zielsystem für Qt entsteht, beschreiben wir unter Embedded Linux und Yocto-BSP.

Adaptive QML-Layouts: eine Oberfläche, die sich anpasst

Multiplattform heißt nicht, überall dieselbe Oberfläche zu zeigen. Mit Qt Quick Layouts und einfachen Zustandsabfragen reagiert dieselbe QML-Datei auf die verfügbare Fläche – ein Dashboard klappt auf dem Panel in eine Spalte, auf dem Desktop in drei:

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

ApplicationWindow {
    id: root
    readonly property bool compact: width < 720

    GridLayout {
        anchors.fill: parent
        columns: root.compact ? 1 : 3

        Repeater {
            model: TelemetryModel        // geteiltes C++-Modell
            delegate: SensorTile {
                Layout.fillWidth: true
                label: model.name
                value: model.value
            }
        }
    }
}

Wo die Unterschiede größer sind als ein Umbruch, greifen File-Selektoren: Qt lädt automatisch die Variante aus einem +-Verzeichnis (etwa +android/Dashboard.qml oder ein eigener Selektor +embedded/), ohne dass der aufrufende Code davon weiß. So bleibt der gemeinsame Pfad sauber, und plattformspezifische Oberflächen leben an genau einer definierten Stelle. Diese QML-Muster sind unser tägliches Handwerk in der Qt/QML-Entwicklung.

Gemeinsame Logik, getrennte Oberflächen

Der Vertrag zwischen Kern und UI ist eine schmale Schnittstelle: QObject-basierte Modelle mit Properties und Signalen. QML bindet deklarativ daran, ohne die Interna der Logik zu kennen.

class DeviceController : public QObject {
    Q_OBJECT
    Q_PROPERTY(double temperature READ temperature NOTIFY temperatureChanged)
public:
    double temperature() const { return m_temperature; }
signals:
    void temperatureChanged();
    // ... gemeinsame Logik für Embedded, Desktop und Mobile
};

Dieselbe DeviceController-Klasse versorgt die HMI auf dem Gerät, die Konfigurationssoftware auf dem Desktop und die mobile App – ohne Duplikate. Ein Fehler in der Temperaturberechnung wird einmal behoben und wirkt sofort auf allen Zielen. Die Disziplin dahinter: In den Kern gehört nur, was plattformunabhängig ist. Alles, was nach Betriebssystem oder Bildschirm fragt, bleibt oberhalb der Schnittstelle.

Ein Build für alle Ziele: CMake und CI

Damit eine Codebasis nicht an drei Toolchains zerbricht, braucht es ein Build-System, das alle Ziele gleich behandelt. In Qt 6 ist das CMake – erstklassig integriert und ideal für Cross-Compiling. Kern und Applikation werden getrennt deklariert, sodass derselbe Kern in jede Zielvariante linkt:

cmake_minimum_required(VERSION 3.21)
project(DeviceSuite LANGUAGES CXX)

find_package(Qt6 REQUIRED COMPONENTS Quick)
qt_standard_project_setup()

# Plattformunabhängiger Kern – einmal deklariert, überall genutzt
qt_add_library(device_core STATIC
    src/DeviceController.cpp
    src/TelemetryModel.cpp
)
target_link_libraries(device_core PUBLIC Qt6::Core)

# Ausführbares Programm je Zielplattform, identischer Kern
qt_add_executable(device_app src/main.cpp)
qt_add_qml_module(device_app
    URI Device.Ui
    QML_FILES qml/Main.qml qml/DashboardDesktop.qml qml/DashboardEmbedded.qml
)
target_link_libraries(device_app PRIVATE device_core Qt6::Quick)

Für das Embedded-Ziel liefert ein Yocto-SDK die passende Toolchain; der Build wird über -DCMAKE_TOOLCHAIN_FILE umgeschaltet, der Quellcode bleibt derselbe. In der CI bildet man daraus eine Build-Matrix: ein Job baut nativ für Desktop, ein weiterer cross für das Board, ein dritter für Mobile. Unit-Tests des Kerns laufen schnell nativ, während der Embedded-Build parallel Kompilierbarkeit und Paketierung absichert. So merkt man Regressionen auf einem Ziel, bevor sie beim Kunden auf dem Gerät landen.

Qt 5 zu Qt 6 als Wegbereiter

Der Wechsel auf Qt 6 hat diesen Ansatz spürbar gestärkt – er ist weniger Pflichtübung als Beschleuniger. Vier Punkte fallen für Multiplattform-Projekte besonders ins Gewicht:

  • CMake als Standard löst qmake ab und macht Cross-Builds sowie die Einbindung in bestehende C++-Ökosysteme deutlich geradliniger.
  • qt_add_qml_module registriert QML-Typen zur Compile-Zeit, was Fehler früher sichtbar macht und die Ahead-of-Time-Kompilierung von QML (qmlsc) ermöglicht – ein Vorteil auf ressourcenschwacher Embedded-Hardware.
  • RHI entkoppelt das Rendering von OpenGL und öffnet moderne Grafik-Backends je Plattform.
  • Bindbare Properties (QProperty) und ein C++17-Fundament machen den Kern schlanker und die Property-Bindungen effizienter.

Ein Wechsel will geplant sein – Qt 5 und Qt 6 unterscheiden sich in Modulzuschnitt und einigen APIs. Sauber getrennte Codebasen migrieren jedoch genau deshalb leichter: Der plattformunabhängige Kern trägt den Großteil der Umstellung, während die UI-Schicht schrittweise nachzieht.

Qt vs. Web/Electron vs. nativ pro Plattform

Die passende Technologie hängt vom Produkt ab. Für Geräteökosysteme, die auch Embedded-Ziele mit begrenzten Ressourcen einschließen, spielt Qt seine Stärken aus:

KriteriumQt (C++/QML)Web / ElectronNativ pro Plattform
Codebasiseine, geteilte Logikeine (Web), aber schwer für Embeddedje Plattform eine
Embedded / Bare-Metalstark (eglfs, Yocto)kaum praktikabelaufwändig, uneinheitlich
Ressourcenbedarfgering bis mittelhoch (Browser-Runtime)gering
Natives Verhaltenanpassbar pro Zielbegrenztmaximal
Hardwarezugriffdirekt aus C++über Brückendirekt
Langzeitwartungeine Codebasiseine, aber Runtime-BallastVielfaches

Web-Stacks glänzen dort, wo ohnehin ein Browser vorhanden ist und Embedded keine Rolle spielt. Rein native Entwicklung liefert das letzte Quäntchen Plattformgefühl – zum Preis paralleler Teams und driftender Featuresets. Qt trifft für Produkte mit echtem Embedded-Anteil den wirtschaftlich vernünftigen Punkt dazwischen.

Fazit

Qt ist mehr als ein UI-Toolkit – richtig eingesetzt wird es zum gemeinsamen technologischen Rückgrat eines ganzen Produktökosystems. Wer Logik und Oberfläche früh trennt, ein CMake-basiertes Build über alle Ziele legt und plattformspezifisches an definierten Stellen kapselt, entwickelt einmal und liefert auf Embedded, Desktop und Mobile. Beispiele solcher Systeme finden Sie in unserem Portfolio. Die Grundlagen dazu vermitteln wir auch in unseren Qt-Schulungen.

Sie planen ein Produkt, das über mehrere Formfaktoren hinweg konsistent funktionieren soll? Sprechen Sie mit uns – wir helfen Ihnen, diese Grundlage von Beginn an richtig zu legen.

Häufige Fragen

Sieht eine Qt-App auf jeder Plattform gleich aus?
Nur, wenn Sie das wollen. Über File-Selektoren, adaptive Layouts und Qt-Quick-Styles lässt sich jede Variante an ihre Plattformkonventionen anpassen, während der Kern identisch bleibt.
Kann ich denselben Code auf einem sparsamen Embedded-Board und auf dem Desktop laufen lassen?
Ja. Der C++/QML-Code ist derselbe; unterschiedlich sind Toolchain (nativ vs. Cross über Yocto-SDK) und das QPA-Backend. Auf schwacher Hardware helfen zusätzlich die QML-Vorab-Kompilierung und ein bewusst schlankes Modul-Set.
Lohnt sich Qt auch, wenn heute nur ein Gerät geplant ist?
Häufig ja. Die saubere Trennung von Logik und UI zahlt sich schon auf einer Plattform aus – und öffnet die Tür für Desktop-Tools oder eine App, ohne dass Sie den Kern neu schreiben.

bitshift dynamics