Qt Embedded Programming – Erste Schritte mit Qt für MCUs

Eingebettete Geräte
2025-01-26
14 Minuten
Qt für MCU

Auf unserem Blog haben wir immer wieder verschiedene „Zweige“ von Qt behandelt, wie z.B. 3D, Android, D-Bus usw. (Das letztere Thema wurde von meinem Kollegen Mateusz behandelt, also lade ich euch ein, einen Blick auf seinen Beitrag über die Nutzung von D-Bus mit Qt 6 zu werfen 🤗).

In der Zwischenzeit, wenn ihr Hilfe bei Qt-Entwicklungsdiensten benötigt, könnt ihr euch gerne bei uns melden!

Es ist also an der Zeit, ein weiteres Gebiet zu erkunden: die Embedded-Programmierung mit Qt für MCU. Ich werde versuchen zu erklären, was Qt für MCUs ist und eine Beispielanwendung zu zeigen, die mit dem Qt-Framework – einem vollständigen Grafikframework – codiert wurde.

Also lasst uns diese interessante Reise beginnen!

 

Ein wenig über das Herz von Embedded-Plattformen

Fangen wir mit der Erklärung des Begriffs M-C-U an. Es steht für „Microcontroller Unit“. Menschen, die mit Elektronik nicht vertraut sind, könnten diesen Begriff als schwierig empfinden, also werde ich versuchen, ihn einfach zu erklären.

Mikrocontroller sind kleine, integrierte elektronische Schaltungen, die einen Mikroprozessor, Programmspeicher, Datenspeicher, verschiedene Ein-/Ausgabe-Schnittstellen (I/O) und oft eine Echtzeituhr (RTC) – alles auf einem einzigen Chip – enthalten.

 

Typische Architektur einer MCU

Mikrocontroller wurden entwickelt, um eine spezifische Aufgabe oder eine Reihe von Aufgaben in einer Vielzahl elektronischer Geräte zu steuern. Sie werden weit verbreitet in Embedded-Plattformen eingesetzt, einschließlich Smartphones, Automotive-Elektronik, Haushaltsgeräten, medizinischen Geräten, industriellen Steuerungen und vielen anderen.

 

Mikrocontroller oder Mikrocomputer – Was ist der Unterschied?

Wenn man über Mikrocontroller spricht, ist es zu Beginn sehr einfach, sie mit Mikrocomputern (auch als Einplatinencomputer bekannt) und manchmal sogar mit Mikroprozessoren zu verwechseln. Unser CTO würde mir einen Kopfstoß geben, wenn ich das nicht erkläre, also lassen Sie uns die Erklärung beginnen 😅.

  • Ein Mikroprozessor ist eine zentrale Verarbeitungseinheit (CPU), die auf einem einzigen integrierten Schaltkreis (Chip) untergebracht ist. Seine Hauptaufgabe ist die Durchführung von arithmetischen-logischen Operationen und die Steuerung des Datenflusses in einem Computersystem. Er besteht normalerweise aus einer arithmetischen Logikeinheit (ALU), einer Steuereinheit, Registern und einem Cache. Der Mikroprozessor ist ein ziemlich komplexes Bauteil, enthält jedoch keine vielen zusätzlichen Funktionen jenseits grundlegender Rechenoperationen.

  • Ein Mikrocontroller ist ein komplettes Computersystem, das auf einem einzigen Chip eingebaut ist. Neben dem Mikroprozessor enthält er Speicher (RAM, ROM/Flash), Ein-/Ausgabe-Schnittstellen (GPIO), Zähler, Timer und oft Kommunikationsmodule. Der Mikrocontroller enthält verschiedene funktionale Blöcke, die es ihm ermöglichen, eine spezifische Aufgabe ohne externe Komponenten auszuführen. Mikrocontroller sind auf eine bestimmte Aufgabe optimiert, was bedeutet, dass sie im Vergleich zu Mikroprozessoren autonomer arbeiten.

  • Ein Mikrocomputer ist ein komplettes Computersystem, das auf einer einzigen Hauptplatine oder in einem einzigen Gehäuse integriert ist (daher der Name: Einplatinencomputer). Er enthält einen Mikroprozessor, Betriebsspeicher, Speicher, Ein-/Ausgabe-Schnittstellen und andere computerspezifische Komponenten. Mikrocomputer sind komplexer als Mikrocontroller und bieten oft die vollständigen Funktionen eines Personal Computers, jedoch im kleineren Maßstab. Im Gegensatz zu Mikrocontrollern sind Mikrocomputer vielseitiger und können für eine breitere Palette von Anwendungen verwendet werden.

Anwendungsfälle – Wo werden sie verwendet?

Wenn wir über Anwendungsfälle für Mikrocontroller sprechen, können wir an einige Beispiele denken, bei denen sie zum Einsatz kommen. Dies sind oft Dinge, die uns umgeben, wie:

  • Verbraucherelektronik: Funktionssteuerung für Fernseher, Waschmaschinen und Kühlschränke.

  • Automotive-Elektronik: Motorsteuerung, Sicherheitssysteme, Navigationssysteme.

  • Industrielle Automatisierung: Prozesssteuerung, Parameterüberwachung, Betrieb von Industrierobotern.

  • Medizinische Systeme: Messung von Blutdruck, Glukose, Defibrillatoren, Beatmungsgeräte.

  • Mobile Geräte: Steuerung von Benutzeroberflächen, drahtloser Konnektivität und GPS-Modulen in Smartphones, Tablets und Smartwatches.

  • Verbraucherelektronik: TV-Fernbedienungen, Blu-ray-Player, Digitalkameras und jedes Kundenendgerät.

  • Internet of Things (IoT): Lampen, Bewegungssensoren und Thermostate, die miteinander und mit der Cloud kommunizieren.

Um eine Vorstellung davon zu bekommen, wie groß der Markt für Mikrocontroller ist, können wir einen Blick auf das folgende Diagramm werfen, das die Größe dieses Marktes zusammen mit einer Schätzung für die kommenden Jahre zeigt.

 

Mikrocontroller-Markt: Größe, Statistiken, 2021 bis 2030

 

Was ist ein Embedded-System?

Es muss angemerkt werden, dass sich Embedded-Plattformen heutzutage weiterentwickelt haben und mit der Entwicklung ihrer Komponenten günstiger geworden sind. Je nach Anwendungsfall muss der Preis der Einzelplatine nicht unbedingt eine Einschränkung darstellen. Zum Beispiel kann im Fall fortschrittlicher medizinischer Systeme der Preis eines einzelnen Geräts leicht bis zu einer halben Million Dollar betragen. In solchen Fällen ist es einfacher, einen leistungsstarken Mikrocomputer mit embedded Linux, Windows Embedded, Embedded Android oder einem anderen High-Level-System zu wählen.

Obwohl dieser Blogbeitrag sich auf Embedded-Systeme bezieht, die auf MCUs laufen, geht es bei Embedded heutzutage nicht nur um Low-Level-Elektronik und Bare-Metal-Systeme. Es geht vielmehr um sogenannte „geschlossene Systeme“.

 

Qt-Framework + MCU = Qt für MCUs!

Okay, wir wissen jetzt, was Mikrocontroller sind, also ist es Zeit, etwas für sie zu programmieren… aber wie?

Nun, hier wird es kompliziert, weil es keine klare Antwort darauf gibt, wie man Mikrocontroller auf Embedded-Plattformen programmiert. Schließlich ist jedes Modell eine andere Technologie. Die meisten von ihnen arbeiten jedoch unter der Kontrolle der Programmiersprachen C/C++, obwohl es manchmal auch möglich ist, Python zu verwenden. Wie du siehst, kann die Entwicklung von Embedded-Software etwas knifflig sein.

Aber wenn du wie ich die Vorteile des Qt-Frameworks nutzen möchtest – ein vollständiges Grafikframework – dann bist du hier… in guten Händen 😉. Hier kommt Qt für MCUs!

Um zu beschreiben, was Qt für MCUs ist, werde ich die Definition aus der offiziellen Qt-Framework-Dokumentation verwenden:

„Qt für MCUs 2.6 bietet ein leichtgewichtiges Grafikframework und Toolkit, mit dem du grafische Benutzeroberflächen (GUIs) auf Mikrocontrollern (MCU) entwerfen, entwickeln und bereitstellen kannst. Es lässt die Ausführung der Anwendung entweder auf Bare-Metal-Systemen oder auf einem Echtzeitbetriebssystem zu.“

Klingt nach allem, was wir brauchen! Als Nebenbemerkung möchte ich noch erklären, was „Bare Metal“ und „Echtzeitbetriebssysteme“ sind:

  • In der Embedded-Programmierung bezieht sich „Bare Metal“ darauf, Software ohne die Verwendung eines Betriebssystems zu schreiben. Es umfasst die direkte Programmierung des Mikrocontrollers, wodurch eine präzise Kontrolle über die Hardwareaspekte möglich wird. Während dieser Ansatz direkten Zugriff auf Hardware-Ressourcen erlaubt, erfordert er auch viel Aufmerksamkeit für Low-Level-Details.

  • Ein Echtzeitbetriebssystem (RTOS) ist ein Betriebssystem, das für die Handhabung von Echtzeitaufgaben optimiert ist und schnelle und zuverlässige Reaktionen auf Ereignisse innerhalb festgelegter Zeitrahmen gewährleistet. RTOS bietet Aufgabenplanung, Interrupt-Verarbeitung und Synchronisationsfunktionen, die es für komplexe Anwendungen wie Flugsteuerungssysteme, Automotive-ABS-Systeme und industrielle Automatisierung geeignet machen. Im Gegensatz zu „Bare Metal“ führt RTOS eine Abstraktionsschicht ein, die das Management und die Entwicklung komplexerer Embedded-Systeme erleichtert. Es ist nicht dasselbe wie embedded Linux.

Es ist auch erwähnenswert, dass Qt mehrere Plattformen von verschiedenen Herstellern wie NXP, Renesas, STM und viele andere unterstützt. In der Dokumentation gibt es eine eigene Seite mit einer Liste unterstützter Boards.

 

Qt Quick Ultralite – Die beste GUI für begrenzte Hardware

Mit Qt für MCUs können wir Anwendungen mit einer grafischen Benutzeroberfläche erstellen, aber es gibt eine Sache, die man beachten muss. Bei der Entwicklung von Embedded-Systemen mit GUI ist es wichtig, die Leistung der Hardware zu berücksichtigen. Dies ist oft eine Herausforderung, je nach der gewählten Zielplattform.

Beim Schreiben von Benutzeroberflächen mit QML für Desktops oder Smartphones müssen wir uns nicht so sehr um die Leistung sorgen, weil unsere Geräte ohnehin mit sehr leistungsstarken Komponenten ausgestattet sind. (Zum Beispiel hat ein durchschnittlicher Computerprozessor eine Taktrate von mehreren Gigahertz, während Mikrocontroller nur eine Taktrate von wenigen Megahertz haben, was einen Unterschied von 1000-mal bedeutet!).

Aus diesem Grund war das „normale“ Qt-Framework für Mikrocontroller ungeeignet, also haben die Experten von Qt etwas Passenderes entwickelt: Qt Quick Ultralite. Ich denke, dies lässt sich am besten durch Zitate aus der Dokumentation beschreiben:

„Qt Quick Ultralite bringt die wichtigsten Funktionen der grafischen Benutzeroberfläche von Qt auf ressourcenbeschränkte Embedded-Systeme, die von Mikrocontrollern (MCU) betrieben werden. Es bietet ein reichhaltiges QML-API-Set zum Erstellen flüssiger GUIs und eine effiziente Grafik-Engine zur Darstellung von Qt-Quick-basierten grafischen Benutzeroberflächen (GUIs).“

„Qt Quick Ultralite berücksichtigt die Ressourcenbeschränkungen auf MCU-Plattformen, wie z.B. den Speicherbedarf und die CPU-Zyklen. Es ermöglicht, dass deine Anwendung mit den verfügbaren Ressourcen auf diesen MCU-Plattformen optimal läuft.“

Für die Neugierigen empfehle ich, die Dokumentation zu lesen, um sich besser damit vertraut zu machen. Im Moment müssen wir nur wissen, dass es wie ein reguläres Qt-Framework funktioniert, jedoch mit einigen Einschränkungen (z.B. weniger Funktionen aus dem Qt Multimedia-Modul).

Es muss zugegeben werden, dass es für den Aufbau von Software auf sehr begrenzter Hardware noch leichtergewichtige Lösungen als Qt für MCUs gibt.

 

Lizenzen für Qt für MCUs – Einige Komplikationen

Okay, ich bin sicher, du bist jetzt schon ein bisschen aufgeregt und deine Hände brennen, um etwas zu programmieren! Lass mich also deine Begeisterung ein wenig bremsen (Entschuldigung 😥).

Ein Thema, das angesprochen werden muss, ist das Lizenzmodell für Qt für MCUs. Zum Zeitpunkt des Schreibens dieses Blogbeitrags ist Qt für MCUs in zwei kommerziellen Lizenzen erhältlich: Qt for Device Creation Professional und Qt for Device Creation Enterprise. Wenn du also Software mit Qt für MCUs erstellen möchtest, musst du eine kommerzielle Qt-Lizenz erwerben.

Wenn du jedoch bereit bist, Qt für MCUs zu testen, hast du die Möglichkeit, eine zeitlich begrenzte Lizenz zu beantragen. Dafür musst du dich jedoch mit der Qt Company in Verbindung setzen.

Die Nachricht, die mich kürzlich sehr gefreut hat, war, dass seit Oktober 2023 Qt für MCU auch als Qt Educational License verfügbar ist, sodass du es als Student zum Lernen des Tools verwenden kannst!

Wenn du Hilfe bei der Wahl der richtigen Lizenz benötigst, kannst du von unserem Beratungsangebot für Qt-Lizenzen Gebrauch machen 😉. Es gibt immer noch die Möglichkeit, Qt in einigen Fällen kostenlos zu nutzen.

 

Derzeit verfügbare Lizenzoptionen

 

Beispiel für die Erstellung von GUI-Programmen mit Qt für MCUs

Nun, wir kennen die Theorien, jetzt ist es Zeit, sie in die Praxis umzusetzen. Als Beispiel werde ich eine einfache Anwendung vorstellen, die eine Liste von Geräten anzeigt, die von Qt für MCUs unterstützt werden.

 

Natürlich gibt es viele weitere unterstützte Plattformen

Der Rest dieses Artikels wird zeigen und erklären, wie man diese Art von Anwendung schreibt. Wie bereits erwähnt, habe ich sie auf einem Emulator ausgeführt, aber wenn Sie einen Mikrocontroller mit einem Bildschirm zur Hand haben, versuchen Sie ruhig, sie darauf auszuführen!

 

Beispiel – Erste Schritte!

Bevor wir mit dem Code selbst fortfahren, müssen zwei Dinge erledigt werden:

1. Laden Sie über das Qt Maintenance Tool das passende Kit für Ihr Board herunter (zum Beispiel STM32F469I-DISCOVERY).

 

Ich habe die neueste verfügbare Version von Qt für MCUs 2.6 verwendet.

2. Bereiten Sie die Hardware vor – dieser Schritt ist jedoch optional, da wir innerhalb von Qt für MCU ein Desktop-Emulator-Kit erhalten, das ich selbst verwendet habe. Sie können alles in der Qt Creator IDE einrichten.

 

Sie sollten Ihr Desktop-Kit hier sehen

Wenn Sie alles eingerichtet haben, müssen Sie nur noch ein neues Projekt erstellen, indem Sie die entsprechende Vorlage auswählen, und das war’s. Kontaktieren Sie uns, wenn Sie eine funktionierende Build-Kette für Ihr Projekt einrichten möchten.

 

Beispiel – CMakeLists.txt und .qmlProject-Dateien

Nach der Erstellung des Projekts erscheint vor unseren Augen eine vertraute Dateistruktur, die jedoch leicht anders ist. Lassen Sie uns zunächst die CMakeLists.txt-Datei besprechen.

 

cmake_minimum_required (VERSION 3.21.1)

project(QtForMCU VERSION 0.0.1 LANGUAGES C CXX ASM)

find_package(Qul)

qul_add_target(QtForMCU QML_PROJECT QtForMCU.qmlproject GENERATE_ENTRYPOINT)

qul_target_generate_interfaces(QtForMCU DeviceModel.h)

target_link_libraries(QtForMCU PRIVATE Qul::Controls)

app_target_setup_os(QtForMCU)

Wie Sie sehen können, haben wir mehrere Funktionen mit dem Präfix qul_ verwendet. Dies sind die Anweisungen, die verwendet werden, um ein Projekt basierend auf Qt Quick Ultralite zu erstellen. Wenn Sie sich diese ansehen, unterscheiden sie sich nicht wesentlich von den Standard-CMake-Anweisungen.

Die nächste Datei ist PROJECT_NAME.qmlProject. Dies ist eine zusätzliche Datei, die verwendet wird, um z. B. Ressourcen, QML-Dateien usw. zu definieren. Sie ist ziemlich groß, daher werde ich nur den wichtigsten Teil einfügen.

 

QmlFiles {
    files: ["QtForMCU.qml"]
  }

  ImageFiles {
    files: [
      "resources/nxp.png",
      "resources/renesas.png",
      "resources/stm.png",
      "resources/infineon.png",
    ]
  }

  FontFiles {
    files: [
      "resources/Roboto/Roboto-Regular.ttf"
    ]
  }

  TranslationFiles {
    files: []
  }

  InterfaceFiles {
    files: ["DeviceModel.h"]
  }

  ModuleFiles {
    files: []
    // Uncomment for adding Qul modules
    MCU.qulModules: [
      "Qul::Controls",
      // "Qul::ControlsTemplates",
      // "Qul::Shapes",
      // "Qul::Timeline"
    ]
 }

 

Beispiel – Interface-Datei – DeviceModel.h

Es ist Zeit, etwas Logik in unsere Anwendung zu integrieren. Mit Qt für MCU wird das Konzept des Qt-Interface-Framework-Moduls angewendet (etwas Ähnliches wie normale Logikklassen). Diese werden automatisch für QML freigegeben, indem sie in der .qmlProject-Datei hinzugefügt werden.

 

#ifndef DEVICEMODEL_H
#define DEVICEMODEL_H

#include <qul/model.h>
#include <platforminterface/allocator.h>
#include <string>

struct Device
{
    std::string name = "";
    int clockSpeed = 0;
    std::string imageSource = "";
};

inline bool operator==(const Device &lhs, const Device &rhs)
{
    return lhs.name == rhs.name &&
           lhs.clockSpeed == rhs.clockSpeed &&
           lhs.imageSource == rhs.imageSource;
}

struct DeviceModel : Qul::ListModel<Device>
{

public:
    DeviceModel() {
        Device nxp{"MIMXRT1050-EVKB", 600, "resources/nxp.png"};
        Device renesas{"EK-RA6M3G", 120, "resources/renesas.png"};
        Device stm{"STM32F769I-DISCOVERY", 216, "resources/stm.png"};
        Device infineon{"TRAVEO T2G TVII-C-2D-4M Evaluation Kit", 240, "resources/infineon.png"};

        m_data.push_back(nxp);
        m_data.push_back(renesas);
        m_data.push_back(stm);
        m_data.push_back(infineon);
    }

    int count() const override {
        return m_data.size();
    }

    Device data(int index) const override {
        return m_data[index];
    }

private:
    Qul::PlatformInterface::Vector<Device> m_data;
};

#endif // DEVICEMODEL_H

Zu Beginn definieren wir uns als Datenstruktur (Device). Diese hat drei Felder: den Gerätenamen, die Taktfrequenz (Timing) und den Pfad zur Grafik.

Als nächstes müssen wir einen Vergleichsoperator für diese Struktur definieren. In diesem Fall sind zwei Instanzen der Device-Klasse gleich, wenn alle Felder gleich sind.

Dann erstellen wir unser Modell. Hier handelt es sich um eine Klasse, die von Qul::ListModel erbt, da unser Modell eine Liste von Objekten der Device-Klasse sein wird. Die Verwendung dieser Klasse erfordert die Implementierung der virtuellen Funktionen count() und data().

In einem privaten Feld der Klasse erstellen wir Qul::PlatformInterface::Vector m_data, in dem wir unsere Objekte speichern.

Zusammengefasst ähnelt die Struktur dieser Datei sehr der Implementierung einer benutzerdefinierten Klasse, die auf QAbstractListModel basiert.

Jetzt müssen Sie nur noch eine einfache GUI in QML erstellen, und fertig! Führen Sie es in Qt Creator aus, und Sie werden den Effekt im Emulator sehen.

 

import QtQuick
import QtQuick.Controls

Rectangle {
  id: root

  width: 640
  height: 480

  color: "#0b2823"

  DeviceModel {
    id: deviceModel
  }

  ListView {
    id: deviceListView

    anchors {
      fill: parent
      margins: 35
    }

    clip: true

    model: deviceModel
    spacing: 35

    delegate: Rectangle {
      color: "#218165"

      width: deviceListView.width
      height: 400

      Image {
        id: deviceImage

        anchors {
          left: parent.left
          top: parent.top
          bottom: parent.bottom
          leftMargin: 25
          topMargin: 75
          bottomMargin: 75
        }

        width: height

        source: model.imageSource
      }

      Text {
        id: nameText

        anchors {
          top: deviceImage.top
          topMargin: 10
          right: parent.right
          rightMargin: 20
          left: deviceImage.right
          leftMargin: 20
        }

        wrapMode: Text.WordWrap

        text: "Model name:\n" + model.name
        font.pixelSize: 32
      }

      Text {
        id: clockSpeedText

        anchors {
          top: nameText.bottom
          topMargin: 20
          right: parent.right
          rightMargin: 20
          left: deviceImage.right
          leftMargin: 20
        }

        wrapMode: Text.WordWrap

       text: "Clock speed:\n" + model.clockSpeed + " MHz"
        font.pixelSize: 26
      }
    }
  }
}

 

Welche Vorteile bietet die Verwendung von Qt-Technologie für Embedded-Geräte?

Ich hoffe, das Beispiel hat Ihnen geholfen, Qt für MCUs zu verstehen. Ich möchte mit ein paar weiteren interessanten Dingen zu diesem Thema abschließen. Unter normalen Bedingungen wird Qt zur Erstellung plattformübergreifender Anwendungen verwendet. Warum ist Qt auch ein vollständiges Grafikframework und eine gute Wahl für Embedded-Plattformen?

Wie Sie vielleicht bemerkt haben, ist die Verwendung von Mikrocontrollern heutzutage sehr verbreitet. Das Beispiel, das ich präsentiert habe, ist ziemlich einfach, aber was, wenn Sie ein komplexes Embedded-Linux-Projekt haben, bei dem Aspekte wie Leistung oder Sicherheit von höchster Bedeutung sind? Für professionellere Anwendungen hat Qt einige nützliche Tools vorbereitet:

  • Qt Application Manager – Qt Application Manager vereinfacht den Lebenszyklus von Anwendungen und bietet Entwicklern eine effiziente Möglichkeit, Software auf Embedded-Linux-Geräten zu installieren, zu steuern und zu aktualisieren.

  • Qt Safe Renderer Modul – Erhöht die Attraktivität der Plattform für sicherheitskritische Anwendungen, insbesondere in Branchen wie der Automobilindustrie. Das Modul gewährleistet einen sicheren Rendering-Prozess, der für Anwendungen, bei denen Sicherheit entscheidend ist, unerlässlich ist.

  • Qt Automotive Suite – Bietet eine umfassende Suite von Tools und Bibliotheken, die speziell für die Automobilentwicklung entwickelt wurden. Diese Suite geht auf die spezifischen Bedürfnisse der Automobilindustrie ein und bietet Lösungen für Infotainmentsysteme, Armaturenbretter und mehr.

  • Boot2Qt – Es handelt sich um eine spezialisierte Lösung, die die Entwicklung und Bereitstellung von Qt-Anwendungen auf Embedded-Linux-Geräten optimiert. Es fungiert als dedizierte Plattform, die den Startprozess optimiert und einen schnellen und effizienten Start von mit dem Qt-Framework entwickelten Anwendungen gewährleistet.

  • Qt Design Studio – Ermöglicht es Entwicklern, ein anspruchsvolles Tool zum Entwerfen und Prototypisieren von Benutzeroberflächen zu verwenden, das speziell für Embedded-Anwendungen entwickelt wurde. Dies erleichtert die Erstellung visuell ansprechender und benutzerfreundlicher Oberflächen.

Natürlich gibt es noch viel mehr. Wenn Sie noch etwas anderes benötigen, empfehle ich Ihnen, die detaillierte API-Dokumentation von Qt zu lesen oder sich direkt an das Qt-Unternehmen (oder uns 😊) zu wenden.

Und das war’s! Ich hoffe, dass Ihnen dieser Blogbeitrag gezeigt hat, wie man auf Embedded-Plattformen mit Qt für MCUs programmiert. Zögern Sie nicht, uns zu kontaktieren, wenn Sie Fragen haben. Bis bald!

 

Scythe-Studio - Qt Developer

Jakub Wincenciak Qt Developer

Brauchen Sie Qt QML-Entwicklungsdienste?

service partner

Kommen wir zur Sache: Es ist eine Herausforderung, Top-Qt-QML-Entwickler zu finden. Helfen Sie sich selbst und starten Sie die Zusammenarbeit mit Scythe Studio – echten Experten im Qt C++ Framework.

Entdecken Sie unsere Fähigkeiten!

Neueste Artikel

[ 154 ]