TouchGFX ist ein von STMicroelectronics bereitgestelltes Framework zur Entwicklung grafischer Benutzeroberflächen (GUI), das für die Entwicklung von Systemen mit STM32-Mikrocontrollern (MCUs) konzipiert ist. Es ermöglicht die Gestaltung objektorientierter Anzeigen und unterstützt STM-MCU-Anwender beim Erstellen flüssiger, ansprechender und vielseitiger Benutzeroberflächen.
Das folgende Beispiel bezieht sich auf TouchGFX Version 4.23.2:

Abbildung 1: Startbildschirm von TouchGFX mit Optionen wie Example, Demo, Create Board chip usw.
Überblick über die Struktur von TouchGFX
Die Architektur des TouchGFX-Programms folgt dem Model-View-Presenter (MVP)-Muster, wie in Abbildung 2 dargestellt, mit den folgenden Vorteilen:
Trennung der Verantwortlichkeiten (Separation of Concerns): Die Wartung des Codes unterscheidet sich je nach Entwicklungsstufe. Dies erleichtert es den Anwendern, Benutzeroberflächen zu erstellen und mit unteren Softwareschichten zu kommunizieren, was zu einer klaren, verständlichen Struktur mit hoher Wiederverwendbarkeit führt.
Modultests (Unit Testing): Die Ansichtsschicht kann direkt mit dem von GFX generierten Code interagieren, was eine unabhängige Validierung der Ergebnisse erleichtert.

Abbildung 2: Beziehungsdiagramm der TouchGFX-Komponenten (MVP)
View: Die von GFX generierte Hauptanzeigeseite zur Darstellung der Benutzeroberfläche. Sie agiert typischerweise als passives Element der oberen MVP-Schicht, verarbeitet alle Gestaltungsinformationen der UI und zeigt Bildschirme entsprechend den Eigenschaften der verwendeten Objekte an.
Model: Dient als zentrale Instanz zur Verarbeitung und Weiterleitung von Daten. Einige Kommunikationspakete werden ausgewertet oder verarbeitet und anschließend über den Presenter an die View gesendet, um den angezeigten Inhalt oder Status von Objekten zu ändern.
Presenter: Vermittelt zwischen View und Model, indem er Datenanforderungen aus dem Model ermöglicht und Funktionen zur Wiederverwendung bereitstellt.
Aufgrund der Firmware-Designphilosophie, die das Model als Steuerzentrale für Befehle definiert, kann das Systemdiagramm wie in Abbildung 3 dargestellt werden.
Durch die Verarbeitung auf niedriger Ebene für verschiedene Schnittstellen (z. B. CAN-Bus, RS485, UART, Bluetooth, Wi-Fi) werden Daten an das Model weitergeleitet und über den Presenter an die View übermittelt, um den Status der Objekte zu aktualisieren.

Abbildung 3: Kommunikation zwischen mehreren Schnittstellen und der MVP-Architektur
Zwei Beispiele verdeutlichen die Methode des Datenaustauschs:
Beispiel 1: Angenommen, der Host sendet einen CANopen-Befehl an das Gerät (Abbildung 4).
CANopen empfängt Pakete über den IF-Port, entschlüsselt gegebenenfalls die Paketdaten über die CAN-Aufgabe und leitet den Inhalt an das Model weiter. Nachdem das Model die Datenbank aktualisiert und den entsprechenden Befehl ausgeführt hat, sendet es das Ergebnis über den Presenter an die View zurück, um die Seite zu aktualisieren.

Abbildung 4: Beispiel eines vom Host gesendeten Befehls
Beispiel 2: Wenn ein Benutzer ein UI-Objekt auf dem Gerät berührt, wird ein Touch-Event-Paket an den Host zurückgemeldet (Abbildung 5).
Wenn ein Benutzer auf ein interaktives Objekt klickt, generiert die View ein Klick-Ereignis, das dann über den Presenter als User Event an das Model übermittelt wird. Das Model reagiert je nach verwendeter Schnittstelle, sendet den Code zurück an die CAN-Aufgabe und überträgt abschließend ein TX-Paket zur Benachrichtigung des Hosts.

Abbildung 5: Vom Benutzer ausgelöstes Touch-Ereignis wird an den Host gesendet
Übersicht über View-Seitenwissen
In der TouchGFX-Softwareoberfläche erzeugt das Design von N Seiten jeweils ein entsprechendes View- und Presenter-Set, jedoch wird nur ein Model alle View-Seiten steuern.
Wenn ein Benutzer ein UI-Szenario entwirft – einschließlich Grafiken, Aussehen, Koordinaten und Textanzeige – erzeugt der Befehl "Code generieren" den entsprechenden Code auf der benannten View-Seite.
Die generierten Ordner sind in ..\generated\ und ..\gui\ unterteilt, wobei ..\generated\ den Basiscode für die gestaltete Seitenanzeige enthält und ..\gui\ die Logik für Objektinteraktionen.
Diese Informationen ermöglichen es uns, Objekte auf ihren jeweiligen Seiten zu platzieren und den verwendbaren Code zu referenzieren.
Hier ist eine einfache Schritt-für-Schritt-Erklärung der obigen Beschreibung:
Zum Beispiel:
1. Öffnen Sie ein leeres Projekt und drücken Sie "Neu erstellen", um ein Projekt zu erstellen (Abbildung 6).

Abbildung 6: TouchGFX Projektstart-Bildschirm
2. In TouchGFX ist standardmäßig ein Screen1 verfügbar. Wir fügen ein neues Button-Objekt hinzu, wählen das gewünschte Bild aus und führen "Code generieren" aus (Abbildung 7).

Abbildung 7: Button-Erstellungs-Demonstration
3. Im Projektpfad erscheinen danach zwei neue Ordner: gui und generated (Abbildung 8):

Abbildung 8: Projektordner-Inhalte
Der Ordner generated enthält den automatisch von TouchGFX erzeugten Basiscode für die Screen1-Komponenten, der nicht direkt bearbeitet werden kann. Wenn sich der Objektstatus auf der Seite ändert und der Code neu aufgebaut wird, wird dieser Ordner aktualisiert.
Ebenso erstellt TouchGFX nach dem Ausführen von "Code generieren" die Datei Screen1ViewBase.cpp unter ..\generated\gui_generated\src\screen1_screen (Abbildung 9).

Abbildung 9: Speicherort von Screen1ViewBase.cpp
Öffnet man Screen1ViewBase.cpp mit Notepad++ (Abbildung 10), sieht man die Eigenschaften und Inhalte der Screen1-Seite sowie die Button-Daten:
- Button-Koordinaten festlegen:
button1.setXY(63, 109);
- Button-Bild-ID festlegen:
button1.setBitmaps(TouchGfx::Bitmap(BITMAP_BUTTON_00_00_ID),TouchGfx::Bitmap(BITMAP_BUTTON_00_00_ID));
- Button-Objekt zur Seite hinzufügen:
Add(button1);

Abbildung 10: Inhalt von Screen1ViewBase.cpp
Der Code in Dateien mit dem Namen XXXBase.cpp wird bei jeder Codegenerierung neu aufgebaut. Änderungen an den Attributdaten wirken sich entsprechend aus. Wenn beispielsweise die Position oder das Bild eines Buttons angepasst wird, ändern sich die Funktionen entsprechend.
Der Ordner gui hingegen erlaubt es dem Benutzer, eigene Logik zu schreiben (Abbildung 8). Hier wird auch die MVP-Architektur erstellt (Abbildungen 11 und 12), sodass eigene Kommunikationsmethoden im Code zur Umsetzung des UI-Designs geplant werden können.

Abbildung 11: Pfad des Modells

Abbildung 12: Pfade von Presenter und View
4. Einfaches Szenario zur Erklärung von GUI/Generated-Design
- Schreiben einer Logik zur Interaktion zwischen einem Button und Text.
- Bei jedem Button-Klick soll der Textwert erhöht werden.
So kann diese Funktionalität umgesetzt werden:
Schritt 1:
Ziehen Sie zwei Objekte auf die Seite: einen Button (button1) und ein Textfeld (textArea1) (Abbildung 13).

Abbildung 13: UI-Designprojekt mit Button-Steuerung
Schritt 2:
Wählen Sie auf der rechten Seite die Interaktionsaktion, fügen Sie ein Button-Klick-Ereignis hinzu und wählen Sie die Funktion add_number aus, die beim Klick ausgeführt werden soll (Abbildung 14).

Abbildung 14: Interaktionsevent hinzufügen
Schritt 3:
In der Datei Screen1ViewBase.cpp (Abbildung 15) sehen Sie den relevanten Code zur Erstellung von button1 und textArea1.
Aufgrund der hinzugefügten Interaktion wird buttonCallbackHandler generiert, um das Button-Touch-Ereignis zu behandeln. Beim Klick wird die Funktion add_number über die Callback-Funktion aufgerufen.

Abbildung 15: Screen1ViewBase.cpp
Inhalt von Screen1ViewBase.hpp (Abbildung 16).

Abbildung 16: Inhalt von Screen1ViewBase.hpp
Schritt 4:
Im gui-Verzeichnis fügen Sie Screen1View.cpp und Screen1View.hpp hinzu.
Fügen Sie das Programm add_number hinzu, um den Parameter count für die Akkumulation zu verwenden (Abbildungen 17 und 18).
Verwenden Sie Unicode: snprintf(textArea1Buffer, TEXTAREA1_SIZE, "%02d", count), um den aktualisierten Zählerwert in textArea1 zu aktualisieren.
Dann textArea1.invalidate(), um die Anzeige zu aktualisieren.

Abbildung 17: Inhalt von Screen1View.cpp

Abbildung 18: Inhalt von Screen1View.hpp
Nach dem Starten des Simulators wird bestätigt, dass bei jedem Klick auf button1 der Wert von textArea1 (count) von 0 aus erhöht wird (Abbildung 19).

Abbildung 19: Anzeige der Simulator-Ergebnisse
Dies bestätigt, dass die Definition von Objekteigenschaften generell im generated-Pfad erfolgt, während der Benutzer seine Logik im gui-Verzeichnis schreibt.
TouchGFX- und Builder-Objekteigenschaften – Beispiele
Der Smart Display GUI Builder von Winstar ist ein Drag-and-Drop-Interface-Design-Tool für UI/UX, das den Kunden einen No-Code-Entwicklungsservice bietet, der auf die schnelle Entwicklung und Gestaltung von Produkten auf Basis von ST MCU zugeschnitten ist. Der GUI Builder wurde als Erweiterung des TouchGFX-Frameworks entwickelt und integriert die ursprünglichen Widget-Funktionen von TouchGFX. Der Hauptunterschied besteht darin, dass mehrere System-Schnittstellen und Kommunikationsprotokolle unterstützt werden. Dies ermöglicht es den Benutzern, direkt zu beobachten, wie Befehle die Steuerung und Änderungen von Widgets beeinflussen.
Hier ist die Einführung zum Builder:
https://www.winstar.com.tw/de/video/play/142.html
Die Designphilosophie von Smartdisplay bezieht sich auf die Funktionalität der TouchGFX-Einstellungen, einschließlich der Firmware, die mit dem STM32 MCU als Grundlage für MVP geschrieben wurde. Die Objekte im Inneren sind mit bestehenden Elementen kombiniert und mit Logik gestaltet.
Daher können einige der Objekte, die vom GUI Builder geöffnet werden, mit bestehenden TouchGFX UI-Komponenten implementiert werden, um entsprechende Anzeigeergebnisse zu erzielen.
*Ergänzender Erklärungsteil
Hier ist ein einfaches Beispiel mit dem Builder-Slider (Abbildung 20):

Abbildung 20: Eigenschaften des Builder-Sliders
Die Eigenschaften des Builder-Sliders sind wie folgt:
Size:
- Width: 618
- Height: 20
Positions:
- Background Position (X): 0
- Background Position (Y): 4
Indicator Position:
- Min: 0
- Max: 580
- Pos: 0
Diese Parameter entsprechen den Slider-Komponenteneinstellungen in TouchGFX (Abbildung 21).

Abbildung 21: Eigenschaften des TouchGFX-Sliders
Die Eigenschaften des TouchGFX-Sliders sind wie folgt:
Location:
- Width: 618
- Height: 20
Positions:
- Background Position (X): 0
- Background Position (Y): 4
Indicator Position:
- Min: 0
- Max: 580
- Y: 0
Benutzer können den Startwert in GFX anpassen, um die Ergebnisse im Builder zu simulieren (Abbildung 22).
Wenn der Wert auf 100 gesetzt wird, kann dasselbe Ergebnis wie im Builder simuliert werden (Abbildung 23).

Abbildung 22: Start = 100 in TouchGFX anpassen

Abbildung 23: Testwert = 100 im Builder anpassen
Wenn wir uns die Datei Screen1ViewBase.cpp ansehen, die von GFX generiert wurde (Abbildung 24):

Abbildung 24: Funktion in Screen1ViewBase.cpp
können wir nachvollziehen, wie die oben genannten Parameter im Code verwendet und angepasst werden. Solche Zahlen stehen in direktem Zusammenhang mit dem Design des GFX-Projekts. Wenn der Builder das Projekt hochlädt, setzt er die Anfangsparameter des Geräte-Sliders zurück.
Wenn der Host einen Befehl zum Ändern des Sliderwerts sendet, wird im view die Methode slider1.setValue() ausgeführt, um die Änderung am Objekt abzuschließen (Abbildung 25).

Abbildung 25: Host sendet Slider-Befehl
Dies ist eine einfache Erklärung der Beziehung zwischen Builder- und TouchGFX-Objekten.
Zukünftige Erweiterungen und Evaluierung der Entwicklung von Builder-Objekten
Mit dem jüngsten Update auf TouchGFX Version 4.24.0 stehen neue Objekte und Funktionen zur Verfügung. Wenn geprüft werden soll, ob diese in den Builder integriert werden können, empfiehlt sich eine erste Evaluierung über die mitgelieferten GFX-Beispiele (Abbildung 26):

Abbildung 26: Verschiedene Beispielprojekte
Da Version 4.24.0 neue Objekte wie QR-Codes unterstützt, können deren Parameter und Funktionen untersucht werden, falls sie in den Builder integriert werden.
Beispiel zur Verwendung eines QR-Codes:
1. Wählen Sie BlankUI.
2. Ziehen Sie das QR-Code-Container-Element hinein.
3. Beobachten Sie die konfigurierbaren Eigenschaften (Abbildung 27):
Location: (X, Y)
Configuration:
- QRVersion
- Scale
- Text
- Error Correction Code…

Abbildung 27: Eigenschaften des QR-Codes
Diese Parameter können anhand der offiziellen Website nachvollzogen werden (Abbildung 28).

Abbildung 28: Erklärung auf der offiziellen Website
In der generierten Funktion Screen1ViewBase.cpp können verfügbare Parameter und Einstellungen überprüft werden (Abbildung 29):
1. Koordinaten setzen: qrCode1.setXY(208, 224);
2. QR-Code-Version setzen: qrCode1.setQRCodeVersion(3);
3. Skalierung setzen: qrCode1.setScale(5);
4. Text eingeben, um den QR-Code zu generieren:
qrCode1.convertStringToQRCode("https://www.winstar.com.tw/zh-tw/");

Abbildung 29: Generierter Code in Screen1ViewBase.cpp
Wenn die QR-Code-Funktion künftig in den Builder integriert wird, können Benutzer diese einstellbaren Parameter direkt setzen.
Referenzen:
https://support.touchgfx.com/docs/category/introduction
https://www.eettaiwan.com/20200203np21/
https://en.wikipedia.org/wiki/STMicroelectronics
https://www.winstar.com.tw/de/video/smartdisplay.html