← How-Tos
electronics 1 hr ago ◯ 5 min read

SquareLine Studio for ESP32 LVGL: Visual GUI Design Without Hand-Coded Widgets

esp32lvglsquareline studiogui designembedded uitft displaytouchscreenarduinoesp-idf

LVGL is the graphics library behind most of the custom touchscreen dashboards on this site, from the Cheap Yellow Display wall panel to the round GC9A01 smart display, but hand-coding every button, slider, and screen transition in C gets tedious fast once a UI has more than a couple of screens. SquareLine Studio is Espressif-recommended drag-and-drop editor for LVGL: you lay out widgets visually, wire up basic behavior with its event system, and export a ready-to-compile C project that drops straight into an Arduino sketch, PlatformIO project, or ESP-IDF component. This guide covers getting a project running, understanding what the exported code actually looks like, and wiring it into firmware you write yourself.

Setting up a project

When you create a new project, SquareLine Studio asks for a target: a specific display resolution, color depth, and the LVGL version to target (v8.x and v9.x behave differently enough that picking the wrong one for your installed LVGL library will cause compile errors). Match this to whatever display and LVGL version your firmware already uses — if you're driving an ILI9341 or ST7789 panel with TFT_eSPI or LovyanGFX and LVGL 8.3, say so at project creation, not after you've built out ten screens.

Building screens without writing widget code

The editor canvas mirrors LVGL's own object tree: everything is a widget nested inside a container, positioned either with fixed coordinates or flex/grid layout (the same layout engine LVGL uses at runtime, so what you see in the editor matches what runs on hardware far more closely than older LVGL GUI tools managed). Drop in panels, labels, buttons, sliders, bars, switches, arcs, and meter/gauge widgets from the component panel, then use the properties panel to set size, color, fonts, and states (pressed, checked, disabled) per widget — including separate styling per state, which is normally one of the more tedious parts of hand-written LVGL code.

Multi-screen projects are managed as named screens in a project tree, with a built-in simulator that renders the UI at your target resolution right in the editor so you can check layout and screen transitions before touching real hardware.

Events: where you actually write code

SquareLine Studio does not pretend to replace your firmware logic, and that's the right design call. Widgets get named, and you attach event triggers (pressed, value changed, screen loaded) to callback functions that are stubbed out in a generated ui_events.c/ui_events.h pair. The exported project leaves these stubs empty on every re-export, so your actual application code — reading a sensor, toggling a GPIO, publishing an MQTT message — lives safely outside the generated files and survives re-exports when you tweak the layout later.

Exported project structure

FileWhat's in itDo you edit it? ui.h / ui.cTop-level init function, screen and widget declarationsNo — regenerated every export ui_ScreenName.cPer-screen widget creation codeNo — regenerated every export ui_events.c / ui_events.hEmpty callback stubs you fill inYes — this is your code ui_helpers.c / ui_helpers.hShared animation/loading helpersNo images/ , fonts/Converted binary image and font dataNo — managed through the editor's asset panel

Wiring it into firmware

  1. Copy the exported ui folder into your Arduino sketch folder or PlatformIO lib/src directory.
  2. In your existing display setup code (the part that already initializes TFT_eSPI/LovyanGFX and calls lv_init()), call ui_init() once after LVGL itself is initialized.
  3. Keep your display flush callback and input device (touch) registration exactly as it already was — SquareLine Studio doesn't touch your driver layer, only the widget tree above it.
  4. Fill in the stub functions in ui_events.c with the actual behavior for each widget interaction.
  5. Re-export whenever you change layout in the editor; your event code in ui_events.c is preserved as long as you don't rename the underlying widgets.

Free vs. paid, and when it matters

SquareLine Studio ships a free Community edition that covers the core workflow described above: unlimited widgets, the simulator, and code export to Arduino/ESP-IDF/PlatformIO. The paid Pro tier adds things aimed at teams and larger products — Figma import for handing a polished design straight to firmware, additional export targets, and collaboration features. For a one-off maker dashboard or product prototype, the free tier is enough; if you're iterating from a designer's Figma mockups or working across a team, the Pro features start paying for themselves.

Practical tips

For anyone who has already hand-built an LVGL dashboard the hard way, the time savings are immediate: what used to be an afternoon of fiddling with pixel offsets and style structs becomes a few minutes of dragging widgets and clicking through state previews, leaving the actual firmware logic as the only part left to write by hand.