Multi-Screen App¶
This example shows how to build a small application with two separate screens and navigate between them.
The key function is mgui_widget_free_screen() — it destroys the current screen and all its children, freeing the memory so the next screen can be created cleanly.
Screenshot¶
Overview¶
┌─────────────────────┐ button click ┌─────────────────────┐
│ App 1 │ ─────────────────────────► │ App 2 │
│ "Go to App 2" │ │ "Go to App 1" │
│ [Button] │ ◄───────────────────────── │ [Button] │
└─────────────────────┘ button click └─────────────────────┘
mgui_widget_free_screen() tears down the current screen before the next one is initialised.
Full Example¶
#include "gui/inc/mgui_hal.h"
#include "gui/inc/mgui_interface.h"
#define SCREEN_WIDTH 240
#define SCREEN_HEIGHT 240
/* ── Forward declarations ───────────────────────────────────────── */
void app1_init(void);
void app2_init(void);
/* ── Screens (only one is alive at a time) ──────────────────────── */
static mgui_widget_t* screen1 = NULL;
static mgui_widget_t* screen2 = NULL;
/* ══════════════════════════════════════════════════════════════════
APP 1
══════════════════════════════════════════════════════════════════ */
static void go_to_app2(mgui_widget_t* obj, mgui_event_t event)
{
(void)obj;
if (event != MGUI_EVENT_CLICKED) return;
/* Free App 1 and its entire widget tree */
mgui_widget_free_screen(&screen1);
/* Build App 2 */
app2_init();
}
void app1_init(void)
{
screen1 = mgui_allocate_widget(
NULL,
MGUI_WIDGET_BOX,
(mgui_area_t){0, 0, SCREEN_WIDTH, SCREEN_HEIGHT},
MGUI_COLOR_DARK_GRAY
);
/* Title label */
mgui_widget_t* title = mgui_allocate_widget(
screen1, MGUI_WIDGET_LABEL,
(mgui_area_t){0, 60, SCREEN_WIDTH, 30},
MGUI_COLOR_WHITE
);
mgui_widget_align(title, MGUI_ALIGN_TOP_CENTER);
mgui_widget_label_set_text(title, "App 1");
/* Navigation button */
mgui_widget_t* btn = mgui_allocate_widget(
screen1, MGUI_WIDGET_BUTTON,
(mgui_area_t){70, 140, 100, 40},
MGUI_COLOR_DEFAULT
);
mgui_widget_button_text(btn, "Go to App 2");
mgui_widget_click_handler(btn, go_to_app2);
}
/* ══════════════════════════════════════════════════════════════════
APP 2
══════════════════════════════════════════════════════════════════ */
static void go_to_app1(mgui_widget_t* obj, mgui_event_t event)
{
(void)obj;
if (event != MGUI_EVENT_CLICKED) return;
/* Free App 2 */
mgui_widget_free_screen(&screen2);
/* Rebuild App 1 */
app1_init();
}
void app2_init(void)
{
screen2 = mgui_allocate_widget(
NULL,
MGUI_WIDGET_BOX,
(mgui_area_t){0, 0, SCREEN_WIDTH, SCREEN_HEIGHT},
MGUI_COLOR_NAVY
);
/* Title label */
mgui_widget_t* title = mgui_allocate_widget(
screen2, MGUI_WIDGET_LABEL,
(mgui_area_t){0, 60, SCREEN_WIDTH, 30},
MGUI_COLOR_WHITE
);
mgui_widget_align(title, MGUI_ALIGN_TOP_CENTER);
mgui_widget_label_set_text(title, "App 2");
/* Navigation button */
mgui_widget_t* btn = mgui_allocate_widget(
screen2, MGUI_WIDGET_BUTTON,
(mgui_area_t){70, 140, 100, 40},
MGUI_COLOR_DEFAULT
);
mgui_widget_button_text(btn, "Go to App 1");
mgui_widget_click_handler(btn, go_to_app1);
}
/* ══════════════════════════════════════════════════════════════════
ENTRY POINT
══════════════════════════════════════════════════════════════════ */
int main(void)
{
mgui_init(SCREEN_WIDTH, SCREEN_HEIGHT, MGUI_BUFFER_SIZE_KB, 30);
app1_init(); /* start with App 1 */
while (1) {
mgui_task_execute();
delay_ms(33);
}
return 0;
}
Key Points¶
mgui_widget_free_screen(&screen)¶
- Frees the screen widget and every child in the tree (buttons, labels, images, …).
- Sets
*screentoNULLso stale pointers are detected immediately. - Call this before creating the next screen to avoid running out of widget memory.
One screen at a time¶
Only one screen should exist at any moment.
The pattern is always:
mgui_widget_free_screen(¤t_screen); /* destroy old screen */
next_screen_init(); /* build new screen */