LVGL GUI-Entwicklung: Ein umfassender Überblick

Software-Entwicklung
2025-06-17
17 Minuten
LVGL GUI-Entwicklung

Grafische Benutzeroberflächen (GUIs) werden in eingebetteten Geräten – von Haushaltsgeräten bis hin zu medizinischer Ausrüstung – zunehmend wichtiger, um eine benutzerfreundliche Erfahrung zu bieten. Doch die Entwicklung einer anspruchsvollen GUI auf ressourcenbeschränkter Hardware ist schwierig. LVGL (Light and Versatile Graphics Library) ist eine beliebte Lösung: ein kostenloses, quelloffenes Grafik-Framework für Mikrocontroller und eingebettete Systeme.

Als Spezialisten für die Entwicklung eingebetteter Systeme sind wir stets auf der Suche nach den besten Lösungen für eine schnelle Entwicklung. In diesem Artikel werfen wir einen genaueren Blick auf LVGL – seine Architektur, Funktionen und Vorteile – um Ihnen bei der Auswahl des richtigen Werkzeugs für Ihre Embedded-Projekte zu helfen.

 

LVGL im Überblick: Architektur & Funktionen

Leichtgewichtige C-Bibliothek

LVGL ist eine in C geschriebene Bibliothek für den Einsatz in eingebetteten Systemen. Sie hat minimale Hardwareanforderungen, läuft auf 16-, 32- oder 64-Bit-MCUs mit einer Taktrate von ≥ 64 MHz und benötigt nur einige Dutzend Kilobyte Speicher (etwa 48 KB RAM und 100 KB Flash für eine einfache GUI). LVGL funktioniert mit jedem MCU/MPU, jedem hochwertigen Display, jedem Betriebssystem oder sogar in Bare-Metal-Umgebungen. Es unterstützt gängige Displaytypen (TFT, OLED, ePaper usw.) sowie verschiedene Farbformate.

 

Modulare Architektur

Im Kern stellt LVGL eine Rendering-Engine für GUIs und eine Objekt-Hierarchie für UI-Elemente (sogenannte „Widgets“) bereit. Entwickler erstellen UI-Objekte (Buttons, Labels, Slider usw.) und LVGL übernimmt deren Darstellung, Eingabeverarbeitung und Animationen. LVGL verwendet ein relatives Layout-System, inspiriert vom Web/CSS-Paradigma – einschließlich Flexbox- und Grid-Layouts – sodass sich Widgets automatisch positionieren und skalieren können.

 

Umfangreiches Widget-Set und Zeichenfunktionen

Trotz seines kleinen Speicherbedarfs bietet LVGL umfassende GUI-Funktionalitäten:

 

  • UI-Widgets: LVGL enthält über 30 integrierte Widgets – Labels, Buttons, Slider, Fortschrittsbalken, Checkboxen, Schalter, Diagramme, Tabellen, Texteingabefelder, Tastaturen, Meldungsfenster und vieles mehr.
  •  

  • Erweiterte 2D-Grafik: Die Software-Rendering-Engine von LVGL unterstützt moderne visuelle Effekte bei hoher Effizienz. Sie zeichnet Formen mit Anti-Aliasing für glatte Kanten und unterstützt Funktionen wie Farbverläufe (linear, radial, konisch), Transparenz, Schatten und Bildtransformationen.
  •  

  • Styling und Themes: Jedes Widget in LVGL ist über ein Stylesystem hochgradig anpassbar. Es gibt über 100 Stil-Eigenschaften (Farben, Abstände, Rahmen usw.), die auf jedes Objekt oder seine Bestandteile angewendet werden können (z. B. kann ein Slider eigene Styles für Regler, Anzeige und Spur haben). Stile können sich automatisch je nach Status (gedrückt, fokussiert, deaktiviert usw.) ändern und mit Übergängen animiert werden.
  •  

  • Internationalisierung: LVGL wurde für den weltweiten Einsatz entwickelt. Es nutzt UTF-8-Codierung und unterstützt komplexe Textdarstellung – einschließlich rechts-nach-links-Schriften (Arabisch, Persisch, Hebräisch) sowie CJK-Zeichen. LVGL kann viele Sprachen und Regionen problemlos unterstützen – auch gemischte LTR- und RTL-Texte in einer Oberfläche.
  •  

  • Eingabeverarbeitung: Neben Touchscreens abstrahiert LVGL Eingabegeräte, sodass Buttons, Drehencoder, Tastaturen oder andere Eingabemethoden als Steuerung verwendet werden können.
  •  

  • Multi-Display und benutzerdefinierte Treiber: LVGL unterstützt mehrere Displays (für Geräte mit mehreren Bildschirmausgängen) sowie Offscreen-Rendering – ideal für kommerzielle Projekte mit vielseitigen Anforderungen an Aufbau, Anschluss und Konfiguration.

 

LVGL Architektur & Funktionen 

LVGL-Bibliothek für die Entwicklung eingebetteter GUIs

LVGL bietet zahlreiche Vorteile für die Entwicklung grafischer Benutzeroberflächen in Embedded-Systemen und ist daher eine beliebte Wahl für viele Entwicklerteams:

 

  1. Kleiner Speicherbedarf & hohe Leistung:
    LVGL ist für ressourcenarme Systeme optimiert, benötigt nur wenige Kilobyte RAM und Flash-Speicher und bietet dennoch flüssige, smartphone-ähnliche Oberflächen. Die Rendering-Engine in C sorgt für hohe Leistung selbst auf stromsparenden Geräten. LVGL kann auf MCUs mit minimalen Ressourcen laufen und dennoch hohe Bildwiederholraten erzielen – ideal für batteriebetriebene Geräte wie Wearables.
  2.  

  3. Umfangreicher Funktionsumfang:
    Trotz seines kleinen Speicherbedarfs bietet LVGL viele Funktionen wie Widgets, Animationen, erweiterte 2D-Grafik, Eingabeverarbeitung und Multitouch-Gesten. Diese Features ermöglichen Entwicklern, attraktive Benutzeroberflächen mit minimalem eigenem Code zu erstellen. LVGL konkurriert mit vielen proprietären GUI-Lösungen und ermöglicht ausgefeilte Benutzeroberflächen auch auf Geräten mit begrenzten Ressourcen.
  4.  

  5. Flexibilität bei Hardware und Betriebssystem:
    LVGL ist äußerst flexibel und unterstützt zahlreiche Hardware-Plattformen und Betriebssysteme. Diese Plattformunabhängigkeit erlaubt es Teams, LVGL auf unterschiedlichen Systemen (z. B. STM32, NXP, Espressif usw.) und Betriebssystemen – ob Bare-Metal oder Linux – zu nutzen. Ein Windows-Simulator ermöglicht die GUI-Entwicklung ohne reale Hardware, was Flexibilität erhöht und Entwicklungsrisiken senkt.
  6.  

  7. Open Source mit aktiver Community:
    LVGL ist quelloffen unter der MIT-Lizenz – keine Lizenzgebühren oder Abgaben, was im Vergleich zu kommerziellen GUI-Bibliotheken Kosten spart. Eine wachsende und aktive Community bietet kontinuierliche Unterstützung, Updates und Fehlerbehebungen. Die Offenheit ermöglicht es Entwicklern, den Quellcode zu debuggen und LVGL bei Bedarf anzupassen. Große Unternehmen wie Xiaomi setzen LVGL in ihren Smart-Produkten ein und tragen zur Weiterentwicklung bei.
  8.  

  9. Anpassbarkeit und Kontrolle:
    LVGL gibt Entwicklern die vollständige Kontrolle über die GUI. Die Bibliothek ist hardwarenah und in C geschrieben, was eine feingranulare Steuerung und einfache Integration ins System ermöglicht. Eigene Widgets und Zeichenroutinen können bei Bedarf hinzugefügt werden, was LVGL besonders für komplexe oder sicherheitskritische Systeme anpassbar macht.
  10.  

  11. Kosteneffizient und kommerziell nutzbar:
    Dank MIT-Lizenz fallen keine versteckten Kosten oder Lizenzgebühren an – LVGL ist sehr kostengünstig. Unternehmen können teure kommerzielle Lizenzen vermeiden und Compliance vereinfachen. Bei Bedarf ist formeller Support verfügbar, aber optional – so bleibt die Flexibilität, den gewünschten Support-Level selbst zu wählen.

 

LVGL GUI Entwicklungsablauf 

Einschränkungen

Kein Framework ist perfekt – es ist wichtig, auch die Einschränkungen und Herausforderungen von LVGL zu berücksichtigen, um eine fundierte Entscheidung zu treffen.

Eine der größten Herausforderungen ist das Fehlen eines nativen GUI-Baukastens. Im Gegensatz zu einigen kommerziellen Alternativen bietet LVGL kein Drag-and-Drop-Tool (nur einen XML-basierten LVGL-Editor). Die Gestaltung von Benutzeroberflächen erfordert meist C-Code oder den Einsatz von Drittanbieter-Tools wie SquareLine Studio oder GUI Guider. Dieser Ansatz bietet mehr Flexibilität, ist jedoch codeintensiver und kann für Teams mit UI-Designern oder visuellen Workflows eine Hürde darstellen. Zudem hat LVGL eine steilere Lernkurve für UX/UI-Designer. Da das Tool keinen Import von grafischen Entwürfen aus Programmen wie Photoshop oder Sketch unterstützt, müssen Entwickler diese Designs manuell umsetzen. Dies kann in größeren Teams zu Reibungen führen – insbesondere wenn Designer nicht programmieren. Doch sobald man mit der LVGL-API vertraut ist, stellt dies oft kein großes Problem mehr dar.

Ein weiterer Aspekt ist der begrenzte offizielle Support und fehlende Garantie. LVGL ist ein Open-Source-Projekt ohne offiziellen Anbieter-Support oder kommerzielle Garantien. Auch wenn die Community wertvolle Ressourcen bietet, könnten Teams, die formellen Support oder Service Level Agreements (SLAs) benötigen, dies im Vergleich zu kommerziellen Lösungen wie Qt for MCUs oder Embedded Wizard als Nachteil empfinden. Die Community und externe Berater können dieses Defizit jedoch teilweise ausgleichen.

Das nischige Ökosystem von LVGL bedeutet, dass es weniger Drittanbieter-Erweiterungen und Integrationen gibt als bei größeren Frameworks wie Qt. Zwar bietet LVGL viele Funktionen von Haus aus, jedoch müssen Teams für spezifische Anforderungen unter Umständen eigene Lösungen entwickeln, da die verfügbaren Ressourcen und die Community kleiner sind.

Darüber hinaus ist LVGL in erster Linie ein GUI-Toolkit, weshalb andere wichtige Funktionen wie Netzwerkkommunikation, Dateisysteme oder Threading-Mechanismen durch separate Bibliotheken oder das zugrunde liegende Betriebssystem abgedeckt werden müssen. Dies ist typisch für eingebettete Systeme, dennoch sollten Teams im Hinterkopf behalten, dass sich LVGL ausschließlich auf die Benutzeroberfläche konzentriert.

Was das Feintuning der Performance betrifft: LVGL ist zwar sehr effizient, aber um optimale Leistung auf ressourcenbeschränkter Hardware zu erreichen, sind manchmal Low-Level-Anpassungen notwendig. Entwickler müssen u. U. das Rendering profilieren und den Speicherverbrauch optimieren, um Probleme wie Flackern oder übermäßige CPU-Auslastung zu vermeiden – besonders bei aufwendigen visuellen Effekten oder bei der Darstellung von Messwerten auf Monitoren. Hier können kommerzielle Lösungen im Vorteil sein, da sie oft bereits hardwareoptimierte Einstellungen mitbringen.

Schließlich kann das manuelle Speichermanagement eine Herausforderung darstellen – insbesondere für Teams, die an höher abstrahierte Frameworks mit Garbage Collection gewöhnt sind. Bei LVGL müssen Entwickler den Speicher manuell verwalten, was eine Umstellung bedeuten kann. Das korrekte Löschen von UI-Objekten und Screens ist entscheidend für die Speicherstabilität.

 

LVGL Einschränkungen
 

Framework-Vergleich: TouchGFX, Qt for MCUs, Embedded Wizard

LVGL ist nicht das einzige Framework für eingebettete GUIs. Weitere beliebte Lösungen sind TouchGFX, Qt for MCUs und Embedded Wizard. Jedes dieser Frameworks hat einen eigenen Ansatz und kann – je nach Projekt – besser oder schlechter geeignet sein. Nachfolgend finden Sie einen kurzen Vergleich dieser Frameworks mit LVGL:

Funktion LVGL TouchGFX Qt for MCUs Embedded Wizard
Lizenz Kostenlos (Open Source) Proprietär (kostenlos für STM32) Kommerziell Kommerziell
Open Source Ja Nein Nein Nein
Zielgruppe Allgemeine Embedded-Systeme STM32-Nutzer Allgemeine Embedded-Systeme (Qt-Nutzer) Allgemeine Embedded-Systeme
Benutzerfreundlichkeit Mittel (manuelles Coden) Hoch (WYSIWYG-Editor) Hoch (UI-Design mit QML) Hoch (WYSIWYG-Editor)
Anpassbarkeit Hoch (volle Kontrolle über den Code) Mittel (eingeschränkte Anpassung) Niedrig (weniger flexibel als LVGL) Mittel (begrenzte Kontrolle über generierten Code)
Hardware-Support Breite Unterstützung von MCUs STM32-Mikrocontroller Ausgewählte MCU-Familien (STM32, NXP, Renesas) Breite Unterstützung von MCU-Familien
Performance Hoch (leichtgewichtig, optimiert) Hoch (optimiert für STM32-Hardware) Mittel (höherer Ressourcenverbrauch) Hoch (optimiert für geringen Speicherbedarf)
Entwicklungstools Manuelles Coden (kein visueller Editor) GUI-Designer (TouchGFX Designer) Qt Design Studio, QML, Qt Quick Ultralite WYSIWYG-Editor, Chora-Sprache
Kosten Kostenlos Kostenlos mit STM32, kommerzielle Nutzung benötigt ST-Lizenz Kommerzielle Lizenz erforderlich Kommerzielle Lizenz erforderlich

Zusammenfassend ergibt sich ein objektives Bild dieser Frameworks:

 

  • LVGL ist Open Source, sehr portabel und kostengünstig, erfordert jedoch mehr Eigenleistung beim Codieren und Support.
  • TouchGFX ist kostenlos und benutzerfreundlich für STM32-Nutzer mit integriertem Designer, bindet jedoch an das ST-Ökosystem und ist geschlossen.
  • Qt for MCUs bietet ein modernes UI-Konzept und leistungsstarke Tools, verursacht jedoch Lizenzkosten und höheren Ressourcenbedarf.
  • Embedded Wizard ermöglicht eine ausgereifte GUI-Entwicklung mit breitem Hardware-Support, ist aber eine proprietäre Lösung mit Investitionsbedarf.

Die Entscheidung hängt von den Projektanforderungen ab – etwa dem verwendeten Mikrocontroller, den Fähigkeiten des Teams, der Komplexität der UI und dem verfügbaren Budget. Viele Hersteller (wie NXP, ST, Renesas) unterstützen in ihren SDKs mehrere dieser Frameworks, da jedes seine eigene Nische hat. Die gute Nachricht ist: LVGL ist oft die flexibelste Wahl, wenn man unabhängig vom Anbieter und kostenbewusst entwickeln möchte – vorausgesetzt, man ist bereit, die GUI selbst zu programmieren.

 

Anwendungsfälle für die LVGL-Grafikbibliothek

Die Vielseitigkeit von LVGL macht es für eine breite Palette von Branchen geeignet. In der Medizintechnik wird es für Benutzeroberflächen von Geräten wie Blutzuckermessgeräten, Herzfrequenzmonitoren und Beatmungsgeräten eingesetzt. Es liefert gestochen scharfe Grafiken und Echtzeitdatenanzeige auf ressourcenarmen Systemen. Sein Open-Source-Charakter ist insbesondere in regulierten Branchen wie dem Gesundheitswesen von Vorteil, da Lizenzprobleme vermieden werden.

In der industriellen Automatisierung kommt LVGL in HMI-Systemen für Steuerungspanels, SPS-Bildschirme und CNC-Maschinen zum Einsatz. Der geringe Ressourcenverbrauch und das deterministische Verhalten machen es ideal für Echtzeitanwendungen mit hoher Zuverlässigkeit. Besonders geschätzt wird in der Industrie die Möglichkeit, Benutzeroberflächen individuell anzupassen – etwa für gebrandete, einzigartige Bedienoberflächen.

In der Unterhaltungselektronik und bei Wearables treibt LVGL Smartwatches, Fitness-Tracker und Haushaltsgeräte an. Dank skinbarer UI und geringer Overhead eignet sich LVGL hervorragend zur Erstellung moderner Benutzeroberflächen mit flüssigen Animationen – selbst auf kostengünstiger Hardware.

Auch im Automobilbereich findet LVGL Anwendung, z. B. für Fahrzeugdisplays, Infotainment-Systeme und digitale Kombiinstrumente – dank schneller Startzeiten und geringem Speicherbedarf. Es wird in eingebetteten Fahrzeuganzeigen genutzt, um verlässliche Grafiken für Navigation, Klimasteuerung und mehr darzustellen.

Insgesamt ist LVGL eine flexible Lösung für Aufgaben der grafischen Benutzeroberfläche in Embedded-Systemen – mit überzeugender Leistung, Zuverlässigkeit und Anpassungsfähigkeit für 2D-orientierte Anwendungen.

LVGL-Codebeispiel für grafische Benutzeroberflächen

In diesem Beispiel erstellen wir ein einfaches Smart-Home-Bedienfeld mit LVGL. Die Oberfläche enthält einen Temperaturanzeige-Button und einen Slider. Der Slider erlaubt dem Benutzer, die Raumtemperatur einzustellen, und der Button zeigt dynamisch den aktuellen Temperaturwert an.

Da LVGL primär für Embedded-Systeme entwickelt wurde, habe ich dieses Beispiel im LVGL-Windows-Simulator ausgeführt. So lässt sich die Anwendung direkt unter Windows entwickeln, testen und aufzeichnen – ganz ohne echte Hardware.

Dieses Setup ist ideal für Prototyping und das Erstellen von Demos wie dieser.

 

LVGL Beispiel-GUI 

Hauptzeile und Hintergrund

Wir beginnen mit der Anpassung des Bildschirmlayouts und bereiten den Bereich vor, der unsere Smart-Home-Steuerelemente aufnehmen soll.

1. Standard-Styles entfernen und dunklen Hintergrund setzen 
Wir entfernen alle bestehenden Styles vom aktiven Bildschirm und setzen einen dunkelgrauen Hintergrund mit voller Deckkraft:

 

lv_obj_remove_style_all(lv_scr_act());
lv_obj_set_style_bg_color(lv_scr_act(), lv_color_hex(0x161616), 0);
lv_obj_set_style_bg_opa(lv_scr_act(), LV_OPA_COVER, 0);

2. Einen horizontalen Container (Hauptzeile) erstellen 
Als Nächstes erstellen wir einen Vollbild-Container, der Button und Slider enthält. Dieser nutzt das Flex-Layout von LVGL mit horizontalem Fluss und Abstand zwischen den Elementen:

 

lv_obj_t *main_row = lv_obj_create(lv_scr_act());
lv_obj_remove_style_all(main_row);
lv_obj_set_size(main_row, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(main_row, LV_FLEX_FLOW_ROW);
lv_obj_set_style_pad_column(main_row, 15, 0); // 15 Pixel Abstand zwischen den Kindelementen
lv_obj_set_style_bg_opa(main_row, LV_OPA_TRANSP, 0);

// Ränder hinzufügen:
lv_obj_set_style_pad_top(main_row, 30, 0);   // 30 Pixel oberer Rand
lv_obj_set_style_pad_left(main_row, 30, 0);  // 30 Pixel linker Rand

lv_obj_align(main_row, LV_ALIGN_CENTER, 0, 0);

Diese main_row dient als Basis-Layout, das den Temperatur-Button und den Slider nebeneinander anordnet.

 

Button

Nun fügen wir links im Panel einen Button hinzu, der die aktuelle Temperatur anzeigt und auf Klicks reagiert.

1. Button erstellen und Styles anwenden 
Wir fügen ein Kindelement zu main_row hinzu, entfernen dessen Standard-Styles und setzen die Größe auf 300×300 Pixel. Der Hintergrund erhält eine dunkelgraue Farbe (#404040), volle Deckkraft und leicht abgerundete Ecken:

 

button = lv_obj_create(main_row);
lv_obj_remove_style_all(button);
lv_obj_set_size(button, 300, 300);
lv_obj_set_style_bg_color(button, lv_color_hex(0x404040), 0);
lv_obj_set_style_bg_opa(button, LV_OPA_COVER, 0);
lv_obj_set_style_radius(button, 8, 0);
lv_obj_align(button, LV_ALIGN_CENTER, 0, 0);

2. Klick-Interaktion hinzufügen 
Wir registrieren eine Callback-Funktion (siehe weiter unten), die auf Klick-Ereignisse reagiert:

 

lv_obj_add_event_cb(button, button_event_cb, LV_EVENT_CLICKED, NULL);

3. Temperatur-Label hinzufügen und stylen 
Innerhalb des Buttons fügen wir ein Label ein, das die aktuelle Temperatur anzeigt. Es wird zentriert und in einem hellgrauen Farbton (#BBBBBB) dargestellt:

 

g_temp_label = lv_label_create(button);
lv_label_set_text_fmt(g_temp_label, "Temperatur: %d°C", temperature);
lv_obj_set_style_text_color(g_temp_label, lv_color_hex(0xBBBBBB), 0);
lv_obj_center(g_temp_label);

Dieser Button dient als dynamische Temperaturanzeige und interaktives Element im Panel.

Slider

Als Nächstes fügen wir rechts im Layout einen vertikalen Slider hinzu. Dieser ermöglicht es dem Benutzer, die Temperatur anzupassen. Ein Label auf dem Slider zeigt dabei in Echtzeit den aktuellen Wert an.

1. Slider erstellen und Größe/Bereich definieren 
Der Slider wird als Kindelement zu main_row hinzugefügt, von Standard-Styles befreit und auf 50×300 Pixel gesetzt. Er wird vertikal zentriert und erlaubt Werte von 0°C bis 30°C, mit einem Anfangswert von 13°C:

 

lv_obj_t *slider = lv_slider_create(main_row);
lv_obj_remove_style_all(slider);
lv_obj_set_size(slider, 50, 300);
lv_obj_align(slider, LV_ALIGN_CENTER, 0, 0);
lv_slider_set_range(slider, 0, 30);
lv_slider_set_value(slider, 13, LV_ANIM_OFF);

2. Hauptspur des Sliders stylen 
Der Hintergrund des Sliders erhält eine dunkelgraue Farbe (#444444), volle Deckkraft und große Rundungen:

 

lv_obj_set_style_bg_color(slider, lv_color_hex(0x444444), LV_PART_MAIN);
lv_obj_set_style_bg_opa(slider, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_radius(slider, 50, LV_PART_MAIN);

3. Gefüllten Bereich (Indikator) stylen 
Der Indikator zeigt, wie viel des Sliders gefüllt ist. Er wird in Rot (#FF0000) dargestellt, mit voller Deckkraft und kleineren Rundungen:

 

lv_obj_set_style_bg_color(slider, lv_color_hex(0xFF0000), LV_PART_INDICATOR);
lv_obj_set_style_bg_opa(slider, LV_OPA_COVER, LV_PART_INDICATOR);
lv_obj_set_style_radius(slider, 10, LV_PART_INDICATOR);

4. Dynamisches Wert-Label hinzufügen 
Im Slider platzieren wir ein Label, das den aktuellen Wert (z. B. „13°C“) anzeigt. Es wird zentriert und in weißem Text dargestellt:

 

lv_obj_t *slider_val_label = lv_label_create(slider);
lv_label_set_text_fmt(slider_val_label, "%d°C", 13);
lv_obj_set_style_text_color(slider_val_label, lv_color_white(), 0);
lv_obj_align(slider_val_label, LV_ALIGN_CENTER, 0, 0);

Wir verknüpfen das Label mit dem Slider per lv_obj_set_user_data(), damit es im Event-Callback dynamisch aktualisiert werden kann.

5. Wertänderungen behandeln 
Zum Schluss registrieren wir einen Callback für Wertänderungen, der Temperatur und Label aktualisiert:

 

lv_obj_set_user_data(slider, slider_val_label);
lv_obj_add_event_cb(slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);

 

Button-Callback

Die Funktion button_event_cb reagiert auf Klick-Ereignisse des Temperatur-Buttons. Beim Klick wechselt ein internes selected-Flag den Zustand, um festzuhalten, ob der Button aktiviert ist.

Visuell zeigt sich die Auswahl durch einen roten Rand um den Button. Wenn der Button ausgewählt ist, wird ein 4 Pixel breiter roter Rahmen hinzugefügt. Bei erneutem Klick und Deaktivierung verschwindet der Rahmen, und der Button erhält wieder sein ursprüngliches graues Aussehen.

 

static void button_event_cb(lv_event_t *e)
{
    selected = !selected;

    if (selected)
    {        
        lv_obj_set_style_border_width(button, 4, 0);
        lv_obj_set_style_border_color(button, lv_color_hex(0xFF0000), 0);
        lv_obj_set_style_border_opa(button, LV_OPA_COVER, 0);
    }
    else
    {
        lv_obj_set_style_border_width(button, 0, 0);
        lv_obj_set_style_bg_color(button, lv_color_hex(0x404040), 0);
        lv_obj_set_style_bg_opa(button, LV_OPA_COVER, 0);
    }
}

 

Slider-Callback

Die Funktion slider_event_cb verarbeitet Änderungen des Slider-Werts. Immer wenn der Benutzer den Slider bewegt, wird dieser Callback ausgelöst.

Zuerst wird geprüft, ob es sich um ein LV_EVENT_VALUE_CHANGED-Ereignis handelt. Dann wird der neue Wert ausgelesen und zwei Labels aktualisiert:

  • Das Label im Slider selbst, das den aktuellen Wert zentriert darstellt (z. B. „17°C“).
  • Das Temperatur-Label im Button, damit beide UI-Elemente synchron sind.

Dadurch bietet der Slider sofortiges Feedback sowohl lokal als auch global in der Oberfläche – für eine intuitive und reaktionsschnelle Temperatursteuerung.

 

static void slider_event_cb(lv_event_t *e)
{
    if (lv_event_get_code(e) == LV_EVENT_VALUE_CHANGED)
    {
        lv_obj_t *slider = lv_event_get_target(e);
        lv_obj_t *slider_val_label = (lv_obj_t *)lv_obj_get_user_data(slider);
        int val = lv_slider_get_value(slider);

        if (slider_val_label)
        {
            lv_label_set_text_fmt(slider_val_label, "%d°C", val);
        }

        if (g_temp_label)
        {
            lv_label_set_text_fmt(g_temp_label, "Temperatur: %d°C", val);
        }
    }
}

Vollständiges Beispiel

Nachfolgend finden Sie den vollständigen Code für unser einfaches Smart-Home-Temperaturpanel mit LVGL. Er enthält das Layout, die interaktiven Komponenten (Button und Slider) sowie deren zugehörige Event-Callbacks für dynamische UI-Aktualisierungen.

 

/**
 * @file lv_demo_scythe.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include "lv_demo_scythe.h"
#include "../../lvgl_private.h"


/* Vorwärtsdeklarationen */
static void button_event_cb(lv_event_t *e);
static void slider_event_cb(lv_event_t *e);

/* Globale Zeiger */
bool selected = false;
int temperature = 13; // Anfangstemperatur
static lv_obj_t *button = NULL;
static lv_obj_t *g_temp_label = NULL;

/***********************************************************
 * HAUPTFUNKTION DER DEMO
 ***********************************************************/

void lv_demo_scythe(void)
{
    /* 1) Hintergrund */
    lv_obj_remove_style_all(lv_scr_act());
    lv_obj_set_style_bg_color(lv_scr_act(), lv_color_hex(0x161616), 0);
    lv_obj_set_style_bg_opa(lv_scr_act(), LV_OPA_COVER, 0);

    // Container für Button und Seitenpanel
    lv_obj_t *main_row = lv_obj_create(lv_scr_act());
    lv_obj_remove_style_all(main_row);
    lv_obj_set_size(main_row, LV_PCT(100), LV_PCT(100));
    lv_obj_set_flex_flow(main_row, LV_FLEX_FLOW_ROW);
    lv_obj_set_style_pad_column(main_row, 15, 0); // 15 Pixel Abstand
    lv_obj_set_style_bg_opa(main_row, LV_OPA_TRANSP, 0);

    // Ränder hinzufügen
    lv_obj_set_style_pad_top(main_row, 30, 0);
    lv_obj_set_style_pad_left(main_row, 30, 0);
    lv_obj_align(main_row, LV_ALIGN_CENTER, 0, 0);

    // Button (links)
    button = lv_obj_create(main_row);
    lv_obj_remove_style_all(button);
    lv_obj_set_size(button, 300, 300);
    lv_obj_set_style_bg_color(button, lv_color_hex(0x404040), 0);
    lv_obj_set_style_bg_opa(button, LV_OPA_COVER, 0);
    lv_obj_set_style_radius(button, 8, 0);
    lv_obj_align(button, LV_ALIGN_CENTER, 0, 0);
    lv_obj_add_event_cb(button, button_event_cb, LV_EVENT_CLICKED, NULL);

    g_temp_label = lv_label_create(button);
    lv_label_set_text_fmt(g_temp_label, "Temperatur: %d°C", temperature);
    lv_obj_set_style_text_color(g_temp_label, lv_color_hex(0xBBBBBB), 0);
    lv_obj_center(g_temp_label);

    // Slider (rechts)
    lv_obj_t *slider = lv_slider_create(main_row);
    lv_obj_remove_style_all(slider);
    lv_obj_set_size(slider, 50, 300);
    lv_obj_align(slider, LV_ALIGN_CENTER, 0, 0);
    lv_slider_set_range(slider, 0, 30);
    lv_slider_set_value(slider, 13, LV_ANIM_OFF);

    lv_obj_set_style_bg_color(slider, lv_color_hex(0x444444), LV_PART_MAIN);
    lv_obj_set_style_bg_opa(slider, LV_OPA_COVER, LV_PART_MAIN);
    lv_obj_set_style_radius(slider, 50, LV_PART_MAIN);

    lv_obj_set_style_bg_color(slider, lv_color_hex(0xFF0000), LV_PART_INDICATOR);
    lv_obj_set_style_bg_opa(slider, LV_OPA_COVER, LV_PART_INDICATOR);
    lv_obj_set_style_radius(slider, 10, LV_PART_INDICATOR);

    lv_obj_t *slider_val_label = lv_label_create(slider);
    lv_label_set_text_fmt(slider_val_label, "%d°C", 13);
    lv_obj_set_style_text_color(slider_val_label, lv_color_white(), 0);
    lv_obj_align(slider_val_label, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_user_data(slider, slider_val_label);
    lv_obj_add_event_cb(slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
}

/***********************************************************
 * CALLBACKS
 ***********************************************************/
static void button_event_cb(lv_event_t *e)
{
    selected = !selected;

    if (selected)
    {
        lv_obj_set_style_border_width(button, 4, 0);
        lv_obj_set_style_border_color(button, lv_color_hex(0xFF0000), 0);
        lv_obj_set_style_border_opa(button, LV_OPA_COVER, 0);
    }
    else
    {
        lv_obj_set_style_border_width(button, 0, 0);
        lv_obj_set_style_bg_color(button, lv_color_hex(0x404040), 0);
        lv_obj_set_style_bg_opa(button, LV_OPA_COVER, 0);
    }
}

static void slider_event_cb(lv_event_t *e)
{
    if (lv_event_get_code(e) == LV_EVENT_VALUE_CHANGED)
    {
        lv_obj_t *slider = lv_event_get_target(e);
        lv_obj_t *slider_val_label = (lv_obj_t *)lv_obj_get_user_data(slider);
        int val = lv_slider_get_value(slider);

        if (slider_val_label)
        {
            lv_label_set_text_fmt(slider_val_label, "%d°C", val);
        }

        if (g_temp_label)
        {
            lv_label_set_text_fmt(g_temp_label, "Temperatur: %d°C", val);
        }
    }
}

 

Ergebnisse und Fazit

Dieses einfache Smart-Home-Panel zeigt, wie schnell man mit LVGL saubere, reaktionsschnelle Benutzeroberflächen erstellen kann. Mit nur wenigen Zeilen Code haben wir ein modernes Layout mit direkter Interaktion zwischen UI-Elementen realisiert – ein Temperatur-Button, der auf Benutzereingaben reagiert, und ein Slider, der die Werte sofort aktualisiert.

 

LVGL Beispiel-GUI 

Dieses Beispiel eignet sich hervorragend als Ausgangspunkt für fortgeschrittene Smart-Home-Oberflächen, Dashboards oder eingebettete Anwendungen. Egal ob Sie Steuerungen für Heizung, Beleuchtung oder Haushaltsgeräte entwickeln – mit LVGL haben Sie die richtigen Werkzeuge zur Hand, um intuitive und visuell ansprechende GUIs zu erstellen.

 

Fazit & weiterführende Ressourcen

Zusammenfassend ist LVGL ein leistungsstarkes Werkzeug, um ansprechende GUIs auf kleinen Mikrocontrollern zu realisieren. Die Welt der grafischen Benutzeroberflächen im Embedded-Bereich ist groß – und wächst stetig weiter. Egal, ob Sie sich für LVGL oder ein anderes Framework entscheiden, das Ziel bleibt dasselbe: eine Oberfläche zu schaffen, die Nutzer begeistert und gleichzeitig den technischen Einschränkungen des Geräts gerecht wird.

Bei der Auswahl eines GUI-Frameworks sollten Sie nicht nur die Bibliothek selbst betrachten, sondern das große Ganze im Blick behalten: die Anforderungen Ihres Produkts, das Know-how Ihres Teams und die langfristige Wartbarkeit. Manche Unternehmen entscheiden sich dafür, mit spezialisierten GUI-Entwicklungspartnern zusammenzuarbeiten. Die Zusammenarbeit mit Entwicklern, die umfassende Erfahrung mit Frameworks wie Qt oder LVGL haben, kann Ihnen eine objektive Einschätzung liefern, welches Werkzeug für Ihr Projekt am besten geeignet ist. Solche Partnerschaften können die Entwicklung beschleunigen und sicherstellen, dass die gewählte Technologie optimal genutzt wird – sei es LVGL oder eine andere Lösung – ohne voreingenommene Präferenzen. Bei Scythe Studio verfügen wir über ein GUI-fokussiertes Entwicklungsteam und haben festgestellt, dass eine gründliche Evaluierung im Vorfeld viel Zeit in späteren Phasen spart. Durch den gezielten Einsatz von Experten treffen Sie die richtige Wahl und implementieren das Framework, das Ihrem Embedded-Produkt die beste Benutzererfahrung bietet.

Wenn Sie LVGL näher kennenlernen möchten, finden Sie hier einige nützliche Ressourcen: Die offizielle LVGL-Dokumentation und Tutorials (verfügbar unter docs.lvgl.io) bieten detaillierte Anleitungen – vom Erstellen einfacher Widgets bis hin zu fortgeschrittener Anpassung. Im GitHub-Repository von LVGL finden Sie viele Beispiele und ein Simulationsprojekt, mit dem Sie gleich loslegen können. Außerdem gibt es ein aktives Forum (forum.lvgl.io), in dem Sie Fragen stellen und sich mit anderen Entwicklern austauschen können, die vor ähnlichen Herausforderungen standen.

Scythe-Studio - Chief Technology Officer

Przemysław Sowa Chief Technology Officer

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

[ 157 ]