Getting Started¶
This page takes you from nothing to a widget on your screen, in four steps. You don't need to know anything about μGui yet — every piece of code is copy-paste, and each step tells you exactly where to paste it.
The whole journey:
- Get the library and add it to your project.
- Copy the Application Skeleton —
a complete, working
main.c. - Connect your display — fill in two small functions.
- Add your first widget — copy it from any widget page.
Once you've done this once, building every future screen is just step 4 again, with a different widget.
Step 1 — Get the library¶
μGui ships as prebuilt packages, one per target. In the repository, pick the
folder that matches your hardware — M0, M4, M7, RISC, ESP32S3, or
Host for the PC simulator — then your colour format (RGB565 /
ARGB8888), input model and display method. Each configuration folder is a
complete, ready-to-build package:
| In the package | What it is |
|---|---|
inc/ |
All μGui headers, plus the fonts, icons and images used across this site — the widget-page examples work out of the box. |
src/libugui.a |
The library itself, prebuilt for that target and configuration. |
main.c |
The Application Skeleton from step 2, already in place. |
CMakeLists.txt |
A working build — link libugui.a and go. |
Wherever you build UI, one include brings in everything:
Step 2 — Copy the Application Skeleton¶
Every μGui application — from a single button to a full patient monitor — has the same shape. That shape is written down once, as one complete file: the Application Skeleton.
Go to the skeleton page, copy the whole skeleton into a new file in your project, and you have a compiling μGui app. Inside it you will find four clearly marked parts:
| Part | What it is |
|---|---|
| Storage | File-scope variables for the screen and each widget. You declare them; the library never allocates memory — there is no heap, no malloc. |
screen_init() |
The function where widgets get built. It's almost empty in the skeleton — your widgets go here in step 4. |
| The HAL | Seven small functions that connect μGui to your hardware. Step 3 fills in the two that matter. |
main() |
Bring-up plus the loop: read input, call ugui_task_execute(), repeat. Already written — you don't touch it. |
Don't try to write this file yourself
The skeleton already handles the things that are easy to get wrong — init order, input injection, the render loop. Start from the copy, not from a blank file.
Step 3 — Connect your display (the HAL)¶
μGui never touches your hardware directly. Instead, it calls a handful of small functions that you write — the HAL. The skeleton contains all of them as empty stubs, and only two need real code before you see pixels:
| Function | What you write in it |
|---|---|
ugui_hal_flush_buffer() |
Send the strip of finished pixels μGui hands you to your panel — usually a SPI/8080 window-set followed by a (DMA) pixel write. |
ugui_hal_get_tick_ms() |
Return your board's millisecond counter (e.g. from SysTick). μGui uses it for animations and press-and-hold timing. |
The rest (init, deinit, debug print, …) can stay empty until you need them. If you forget one entirely, the build fails at link time — so nothing can go missing silently.
Different display setups
The default drawing mode renders through one small line buffer — the lowest-RAM option, right for most SPI panels. If your hardware has framebuffers or hardware layers, the skeleton lists the bring-up for all seven display modes — only two lines change.
Step 4 — Add your first widget¶
Every page in the Widget Catalog shows complete, copy-paste examples next to the exact frame they render. Adding a widget to your skeleton is always the same two pastes.
Using the Button as the example:
Paste 1 — the storage, at file scope, next to the skeleton's s_screen
and s_root:
Paste 2 — the build calls, inside screen_init(), where the skeleton
says /* --- your widgets go here --- */:
ugui_widget_button_init(&s_root, &s_demo_btn, &s_demo_btn_ext);
ugui_screen_add_widget(&s_screen, &s_demo_btn);
Build and run. A themed, rounded, centred button appears — no colors, sizes
or positions needed, because *_init() applies good defaults for
everything. Every setter you see on the widget pages (set_text,
set_area, set_style, …) is an optional refinement on top.
Want the button to say something and react to taps? The Button page's second example adds a caption and a click callback — copy it the same way. And that's the entire workflow for all 35 widget families.
Three rules that explain everything¶
If you remember only three things about μGui, make them these:
- A widget is two structs, and you own both. The generic
ugui_widget_tplus a small per-family_extstruct (ugui_button_ext_t,ugui_slider_ext_t, …), declared at file scope. The library never allocates — your RAM budget is known at link time. *_init()already looks right. Every widget comes out themed, sized and anti-aliased. Style setters are opt-in, which is why the examples are so short.- Register every widget.
ugui_screen_add_widget()after every*_init()— a widget that isn't registered is never drawn and never receives touch. If something doesn't show up, check this first.
More gotchas (frozen animations, unresponsive touch) are collected in the skeleton's Things people miss.
Where to next¶
- Application Skeleton — the file from step 2, with display-mode bring-ups, widget IDs and multi-screen apps explained.
- Widget Catalog — all documented families, each with screenshots and complete copy-paste examples.
- Examples — four complete products (patient monitor, automotive cluster, coffee machine, smart home) built from the same widgets you just used.
- Tools — the designer, font and image pipeline that ship alongside the library.