### Initial settings.json Example Source: https://lvgl.io/docs/open/9.4/details/integration/chip_vendors/alif/overview.html Shows the initial state of the VS Code user settings JSON before adding the required Alif tool paths. This is the starting point for the configuration step. ```json { "workbench.colorTheme": "Default Dark+", "editor.renderWhitespace": "all", } ``` -------------------------------- ### Build and install the SDK Source: https://lvgl.io/docs/open/9.4/details/integration/embedded_linux/os/buildroot/quick_setup.html Builds the SDK and installs it to ~/sdk. The SDK is required to compile the application. ```bash cd output make sdk mkdir -p ~/sdk tar -xzf images/aarch64-buildroot-linux-gnu_sdk-buildroot.tar.gz -C ~/sdk ``` -------------------------------- ### Simple Roller Example (lv_example_roller_1) Source: https://lvgl.io/docs/open/9.4/examples.html Creates an infinite roller with month names, sets visible row count to 4, centers it, and logs the selected month on value change. Requires LV_USE_ROLLER and LV_BUILD_EXAMPLES. ```C #include "../../lv_examples.h" #if LV_USE_ROLLER && LV_BUILD_EXAMPLES static void event_handler(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); lv_obj_t * obj = lv_event_get_target_obj(e); if(code == LV_EVENT_VALUE_CHANGED) { char buf[32]; lv_roller_get_selected_str(obj, buf, sizeof(buf)); LV_LOG_USER("Selected month: %s\n", buf); } } /** * An infinite roller with the name of the months */ void lv_example_roller_1(void) { lv_obj_t * roller1 = lv_roller_create(lv_screen_active()); lv_roller_set_options(roller1, "January\n" "February\n" "March\n" "April\n" "May\n" "June\n" "July\n" "August\n" "September\n" "October\n" "November\n" "December", LV_ROLLER_MODE_INFINITE); lv_roller_set_visible_row_count(roller1, 4); lv_obj_center(roller1); lv_obj_add_event_cb(roller1, event_handler, LV_EVENT_ALL, NULL); } #endif ``` -------------------------------- ### Simple LVGL Berry example: create button and label Source: https://lvgl.io/docs/open/9.4/details/integration/frameworks/tasmota-berry.html Starts LVGL, gets the active screen, creates a button, centers it, adds a label, and sets its text. This is the introductory example for using LVGL with Berry in Tasmota. ```berry lv.start() # start LVGL scr = lv.screen_active() # get default screen btn = lv.btn(scr) # create button btn.center() label = lv.label(btn) # create a label in the button label.set_text("Button") # set a label to the button ``` -------------------------------- ### Create LED with custom style and brightness (lv_example_led_1) Source: https://lvgl.io/docs/open/9.4/examples.html Creates three LEDs with different brightness and color using lv_led_create, lv_led_off, lv_led_set_brightness, lv_led_set_color, and lv_led_on. Requires LV_USE_LED and LV_BUILD_EXAMPLES to be enabled. ```C #include "../../lv_examples.h" #if LV_USE_LED && LV_BUILD_EXAMPLES /** * Create LED's with different brightness and color */ void lv_example_led_1(void) { /*Create a LED and switch it OFF*/ lv_obj_t * led1 = lv_led_create(lv_screen_active()); lv_obj_align(led1, LV_ALIGN_CENTER, -80, 0); lv_led_off(led1); /*Copy the previous LED and set a brightness*/ lv_obj_t * led2 = lv_led_create(lv_screen_active()); lv_obj_align(led2, LV_ALIGN_CENTER, 0, 0); lv_led_set_brightness(led2, 150); lv_led_set_color(led2, lv_palette_main(LV_PALETTE_RED)); /*Copy the previous LED and switch it ON*/ lv_obj_t * led3 = lv_led_create(lv_screen_active()); lv_obj_align(led3, LV_ALIGN_CENTER, 80, 0); lv_led_on(led3); } #endif ``` -------------------------------- ### Create a simple list with buttons and event handler (lv_example_list_1) Source: https://lvgl.io/docs/open/9.4/examples.html Builds a list with text headers and buttons, attaching an event handler that logs the clicked button text using lv_list_get_button_text. Requires LV_USE_LIST and LV_BUILD_EXAMPLES to be enabled. ```C #include "../../lv_examples.h" #if LV_USE_LIST && LV_BUILD_EXAMPLES static lv_obj_t * list1; static void event_handler(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); lv_obj_t * obj = lv_event_get_target_obj(e); if(code == LV_EVENT_CLICKED) { LV_UNUSED(obj); LV_LOG_USER("Clicked: %s", lv_list_get_button_text(list1, obj)); } } void lv_example_list_1(void) { /*Create a list*/ list1 = lv_list_create(lv_screen_active()); lv_obj_set_size(list1, 180, 220); lv_obj_center(list1); /*Add buttons to the list*/ lv_obj_t * btn; lv_list_add_text(list1, "File"); btn = lv_list_add_button(list1, LV_SYMBOL_FILE, "New"); lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, NULL); btn = lv_list_add_button(list1, LV_SYMBOL_DIRECTORY, "Open"); lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, NULL); btn = lv_list_add_button(list1, LV_SYMBOL_SAVE, "Save"); lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, NULL); btn = lv_list_add_button(list1, LV_SYMBOL_CLOSE, "Delete"); lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, NULL); btn = lv_list_add_button(list1, LV_SYMBOL_EDIT, "Edit"); lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, NULL); lv_list_add_text(list1, "Connectivity"); btn = lv_list_add_button(list1, LV_SYMBOL_BLUETOOTH, "Bluetooth"); lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, NULL); btn = lv_list_add_button(list1, LV_SYMBOL_GPS, "Navigation"); lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, NULL); btn = lv_list_add_button(list1, LV_SYMBOL_USB, "USB"); lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, NULL); btn = lv_list_add_button(list1, LV_SYMBOL_BATTERY_FULL, "Battery"); lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, NULL); lv_list_add_text(list1, "Exit"); btn = lv_list_add_button(list1, LV_SYMBOL_OK, "Apply"); lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, NULL); btn = lv_list_add_button(list1, LV_SYMBOL_CLOSE, "Close"); lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, NULL); } #endif ``` -------------------------------- ### Style a button from scratch (lv_example_button_2) Source: https://lvgl.io/docs/open/9.4/examples.html Creates a button with custom styles for default and pressed states, including gradients, borders, shadows, outlines, and transitions. Requires LV_USE_BUTTON and LV_BUILD_EXAMPLES. ```C #include "../../lv_examples.h" #if LV_USE_BUTTON && LV_BUILD_EXAMPLES /** * Style a button from scratch */ void lv_example_button_2(void) { /*Init the style for the default state*/ static lv_style_t style; lv_style_init(&style); lv_style_set_radius(&style, 3); lv_style_set_bg_opa(&style, LV_OPA_100); lv_style_set_bg_color(&style, lv_palette_main(LV_PALETTE_BLUE)); lv_style_set_bg_grad_color(&style, lv_palette_darken(LV_PALETTE_BLUE, 2)); lv_style_set_bg_grad_dir(&style, LV_GRAD_DIR_VER); lv_style_set_border_opa(&style, LV_OPA_40); lv_style_set_border_width(&style, 2); lv_style_set_border_color(&style, lv_palette_main(LV_PALETTE_GREY)); lv_style_set_shadow_width(&style, 8); lv_style_set_shadow_color(&style, lv_palette_main(LV_PALETTE_GREY)); lv_style_set_shadow_offset_y(&style, 8); lv_style_set_outline_opa(&style, LV_OPA_COVER); lv_style_set_outline_color(&style, lv_palette_main(LV_PALETTE_BLUE)); lv_style_set_text_color(&style, lv_color_white()); lv_style_set_pad_all(&style, 10); /*Init the pressed style*/ static lv_style_t style_pr; lv_style_init(&style_pr); /*Add a large outline when pressed*/ lv_style_set_outline_width(&style_pr, 30); lv_style_set_outline_opa(&style_pr, LV_OPA_TRANSP); lv_style_set_translate_y(&style_pr, 5); lv_style_set_shadow_offset_y(&style_pr, 3); lv_style_set_bg_color(&style_pr, lv_palette_darken(LV_PALETTE_BLUE, 2)); lv_style_set_bg_grad_color(&style_pr, lv_palette_darken(LV_PALETTE_BLUE, 4)); /*Add a transition to the outline*/ static lv_style_transition_dsc_t trans; static lv_style_prop_t props[] = {LV_STYLE_OUTLINE_WIDTH, LV_STYLE_OUTLINE_OPA, 0}; lv_style_transition_dsc_init(&trans, props, lv_anim_path_linear, 300, 0, NULL); lv_style_set_transition(&style_pr, &trans); lv_obj_t * btn1 = lv_button_create(lv_screen_active()); lv_obj_remove_style_all(btn1); /*Remove the style coming from the theme*/ lv_obj_add_style(btn1, &style, 0); lv_obj_add_style(btn1, &style_pr, LV_STATE_PRESSED); lv_obj_set_size(btn1, LV_SIZE_CONTENT, LV_SIZE_CONTENT); lv_obj_center(btn1); lv_obj_t * label = lv_label_create(btn1); lv_label_set_text(label, "Button"); lv_obj_center(label); } #endif ``` -------------------------------- ### Simple Menu with root btn (lv_example_menu_2) Source: https://lvgl.io/docs/open/9.4/examples.html Creates a menu with a root back button enabled via LV_MENU_ROOT_BACK_BUTTON_ENABLED. Clicking the root back button shows a message box with 'Hello' and 'Root back btn click.' text. Requires LV_USE_MENU, LV_USE_MSGBOX, and LV_BUILD_EXAMPLES. ```c #include "../../lv_examples.h" #if LV_USE_MENU && LV_USE_MSGBOX && LV_BUILD_EXAMPLES static void back_event_handler(lv_event_t * e) { lv_obj_t * obj = lv_event_get_target_obj(e); lv_obj_t * menu = (lv_obj_t *)lv_event_get_user_data(e); if(lv_menu_back_button_is_root(menu, obj)) { lv_obj_t * mbox1 = lv_msgbox_create(NULL); lv_msgbox_add_title(mbox1, "Hello"); lv_msgbox_add_text(mbox1, "Root back btn click."); lv_msgbox_add_close_button(mbox1); } } void lv_example_menu_2(void) { lv_obj_t * menu = lv_menu_create(lv_screen_active()); lv_menu_set_mode_root_back_button(menu, LV_MENU_ROOT_BACK_BUTTON_ENABLED); lv_obj_add_event_cb(menu, back_event_handler, LV_EVENT_CLICKED, menu); lv_obj_set_size(menu, lv_display_get_horizontal_resolution(NULL), lv_display_get_vertical_resolution(NULL)); lv_obj_center(menu); lv_obj_t * cont; lv_obj_t * label; /*Create a sub page*/ lv_obj_t * sub_page = lv_menu_page_create(menu, NULL); cont = lv_menu_cont_create(sub_page); label = lv_label_create(cont); lv_label_set_text(label, "Hello, I am hiding here"); /*Create a main page*/ lv_obj_t * main_page = lv_menu_page_create(menu, NULL); cont = lv_menu_cont_create(main_page); label = lv_label_create(cont); lv_label_set_text(label, "Item 1"); cont = lv_menu_cont_create(main_page); label = lv_label_create(cont); lv_label_set_text(label, "Item 2"); cont = lv_menu_cont_create(main_page); label = lv_label_create(cont); lv_label_set_text(label, "Item 3 (Click me!)"); lv_menu_set_load_page_event(menu, cont, sub_page); lv_menu_set_page(menu, main_page); } #endif ``` -------------------------------- ### Complex Menu with sliders, switches, and back button (lv_example_menu_5) Source: https://lvgl.io/docs/open/9.4/examples.html Builds a full-screen menu with sub-pages for mechanics and sound settings, using sliders and switches. Enables the root back button and adjusts the menu background based on brightness. Requires LV_USE_MENU, LV_USE_MSGBOX, and LV_BUILD_EXAMPLES. ```C #include "../../lv_examples.h" #if LV_USE_MENU && LV_USE_MSGBOX && LV_BUILD_EXAMPLES typedef enum { LV_MENU_ITEM_BUILDER_VARIANT_1, LV_MENU_ITEM_BUILDER_VARIANT_2 } lv_menu_builder_variant_t; static void back_event_handler(lv_event_t * e); static void switch_handler(lv_event_t * e); static lv_obj_t * root_page; static lv_obj_t * create_text(lv_obj_t * parent, const char * icon, const char * txt, lv_menu_builder_variant_t builder_variant); static lv_obj_t * create_slider(lv_obj_t * parent, const char * icon, const char * txt, int32_t min, int32_t max, int32_t val); static lv_obj_t * create_switch(lv_obj_t * parent, const char * icon, const char * txt, bool chk); void lv_example_menu_5(void) { lv_obj_t * menu = lv_menu_create(lv_screen_active()); lv_color_t bg_color = lv_obj_get_style_bg_color(menu, LV_PART_MAIN); if(lv_color_brightness(bg_color) > 127) { lv_obj_set_style_bg_color(menu, lv_color_darken(lv_obj_get_style_bg_color(menu, LV_PART_MAIN), 10), 0); } else { lv_obj_set_style_bg_color(menu, lv_color_darken(lv_obj_get_style_bg_color(menu, LV_PART_MAIN), 50), 0); } lv_menu_set_mode_root_back_button(menu, LV_MENU_ROOT_BACK_BUTTON_ENABLED); lv_obj_add_event_cb(menu, back_event_handler, LV_EVENT_CLICKED, menu); lv_obj_set_size(menu, lv_display_get_horizontal_resolution(NULL), lv_display_get_vertical_resolution(NULL)); lv_obj_center(menu); lv_obj_t * cont; lv_obj_t * section; /*Create sub pages*/ lv_obj_t * sub_mechanics_page = lv_menu_page_create(menu, NULL); lv_obj_set_style_pad_hor(sub_mechanics_page, lv_obj_get_style_pad_left(lv_menu_get_main_header(menu), LV_PART_MAIN), 0); lv_menu_separator_create(sub_mechanics_page); section = lv_menu_section_create(sub_mechanics_page); create_slider(section, LV_SYMBOL_SETTINGS, "Velocity", 0, 150, 120); create_slider(section, LV_SYMBOL_SETTINGS, "Acceleration", 0, 150, 50); create_slider(section, LV_SYMBOL_SETTINGS, "Weight limit", 0, 150, 80); lv_obj_t * sub_sound_page = lv_menu_page_create(menu, NULL); lv_obj_set_style_pad_hor(sub_sound_page, lv_obj_get_style_pad_left(lv_menu_get_main_header(menu), LV_PART_MAIN), 0); lv_menu_separator_create(sub_sound_page); section = lv_menu_section_create(sub_sound_page); create_switch(section, LV_SYMBOL_AUDIO, "Sound", false); ``` -------------------------------- ### Enable demos and examples Source: https://lvgl.io/docs/open/9.4/details/integration/building/cmake.html Enables the demos and examples by setting `CONFIG_LV_BUILD_EXAMPLES` and `CONFIG_LV_BUILD_DEMOS` to ON. ```cmake set(CONFIG_LV_BUILD_EXAMPLES ON) set(CONFIG_LV_BUILD_DEMOS ON) add_subdirectory(lvgl) ``` -------------------------------- ### Clone the LVGL Buildroot repository Source: https://lvgl.io/docs/open/9.4/details/integration/embedded_linux/os/buildroot/quick_setup.html Clones the lv_buildroot repository with all submodules, providing everything needed to test the Buildroot setup without following the guide. ```bash git clone --recurse-submodules https://github.com/lvgl/lv_buildroot.git ``` -------------------------------- ### Clone alif_m55-lvgl Repository Source: https://lvgl.io/docs/open/9.4/details/integration/chip_vendors/alif/overview.html Clones the Alif LVGL example project with submodules using `--recursive`. This is required to get the LVGL example project running on the Alif E7 Devkit Gen2. ```bash git clone --recursive https://github.com/alifsemi/alif_m55-lvgl ``` -------------------------------- ### Install Yocto SDK with poky-glibc-x86_64-core-image-base-cortexa53-raspberrypi3-64-toolchain-5.0.4.sh Source: https://lvgl.io/docs/open/9.4/details/integration/embedded_linux/os/yocto/lvgl_recipe.html Execute the generated SDK installer script to install the SDK. The example shows entering /opt/poky/sdk-with-lvgl as the target directory and confirming the installation with 'y'. ```bash $ ./sdk/poky-glibc-x86_64-core-image-base-cortexa53-raspberrypi3-64-toolchain-5.0.4.sh Poky (Yocto Project Reference Distro) SDK installer version 5.0.4 ================================================================= Enter target directory for SDK (default: /opt/poky/5.0.4): /opt/poky/sdk-with-lvgl You are about to install the SDK to "/opt/poky/sdk-with-lvgl". Proceed [Y/n]? y ``` -------------------------------- ### Basic GStreamer application setup with LVGL Source: https://lvgl.io/docs/open/9.4/details/libs/gstreamer.html Minimal main() that initializes LVGL, creates a display, runs the GStreamer example, and enters the LVGL timer loop. ```c int main(void) { /* Initialize LVGL */ lv_init(); /* Setup display driver */ lv_display_t *display = lv_display_create(800, 480); /* ... configure display driver ... */ /* Create and run your GStreamer application */ lv_example_gstreamer_1(); while (1) { lv_timer_handler(); } return 0; } ``` -------------------------------- ### Hello World LVGL application for QNX Source: https://lvgl.io/docs/open/9.4/details/integration/rtos/qnx.html Shows how to initialize LVGL, create a window, add input devices, create a UI, and run the event loop using QNX-specific calls. ```c #include int main(int argc, char **argv) { /* Initialize the library. */ lv_init(); /* Create a 800x480 window. */ lv_display_t *disp = lv_qnx_window_create(800, 480); lv_qnx_window_set_title(disp, "LVGL Example"); /* Add keyboard and mouse devices. */ lv_qnx_add_keyboard_device(disp); lv_qnx_add_pointer_device(disp); /* Generate the UI. */ lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0x003a57), LV_PART_MAIN); lv_obj_t * label = lv_label_create(lv_screen_active()); lv_label_set_text(label, "Hello world"); lv_obj_set_style_text_color(lv_screen_active(), lv_color_hex(0xffffff), LV_PART_MAIN); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); /* Run the event loop until it exits. */ return lv_qnx_event_loop(disp); } ``` -------------------------------- ### Simple bar example: lv_example_bar_1 Source: https://lvgl.io/docs/open/9.4/examples.html Creates a centered bar widget with size 200x20 and sets its value to 70 without animation. Requires LV_USE_BAR and LV_BUILD_EXAMPLES. ```C #include "../../lv_examples.h" #if LV_USE_BAR && LV_BUILD_EXAMPLES void lv_example_bar_1(void) { lv_obj_t * bar1 = lv_bar_create(lv_screen_active()); lv_obj_set_size(bar1, 200, 20); lv_obj_center(bar1); lv_bar_set_value(bar1, 70, LV_ANIM_OFF); } #endif ``` -------------------------------- ### File Explorer Example 2: Main Function with Platform-Specific Setup Source: https://lvgl.io/docs/open/9.4/details/auxiliary-modules/file_explorer.html Creates a file explorer and configures it for Windows or Linux. For Windows, it opens 'C:C:/' and sets quick access paths for common directories. For Linux, it opens 'A:/' and builds quick access paths from the HOME environment variable. It also adds an event handler and, if quick access is enabled, creates a checkable button to toggle the quick access area and a dropdown for sort control. ```c void lv_example_file_explorer_2(void) { lv_obj_t * file_explorer = lv_file_explorer_create(lv_screen_active()); #if LV_USE_FS_WIN32 /* Note to Windows users: the initial "C:" on these paths corresponds to * the value of `LV_FS_WIN32_LETTER` in `lv_conf.h`, and should not be * confused with the Windows/DOS drive letter. It is an identifier that * is used to enable LVGL to look up the appropriate driver from a list of * registered file-system drivers. `lv_fs_win32_init()` happens to use the * identifier letter 'C' so "C:" is the driver-identifier-prefix used here. * The "C:" following that is indeed the Windows/DOS drive letter and is * part of the actual path that gets passed to the OS-level functions. * * See https://lvgl.io/docs/open/master/details/main-components/fs.html for details. * File Explorer uses `lv_fs` internally, thus the required prefix in path strings. */ lv_file_explorer_open_dir(file_explorer, "C:C:/"); #if LV_FILE_EXPLORER_QUICK_ACCESS lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, "C:C:/Users/Public/Desktop"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, "C:C:/Users/Public/Videos"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, "C:C:/Users/Public/Pictures"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, "C:C:/Users/Public/Music"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, "C:C:/Users/Public/Documents"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "C:C:/"); #endif #else /* linux */ lv_file_explorer_open_dir(file_explorer, "A:/"); #if LV_FILE_EXPLORER_QUICK_ACCESS const char * envvar = "HOME"; char home_dir[LV_FS_MAX_PATH_LENGTH]; strcpy(home_dir, "A:"); /* get the user's home directory from the HOME environment variable*/ strcat(home_dir, getenv(envvar)); LV_LOG_USER("home_dir: %s\n", home_dir); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, home_dir); char video_dir[LV_FS_MAX_PATH_LENGTH]; strcpy(video_dir, home_dir); strcat(video_dir, "/Videos"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, video_dir); char picture_dir[LV_FS_MAX_PATH_LENGTH]; strcpy(picture_dir, home_dir); strcat(picture_dir, "/Pictures"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, picture_dir); char music_dir[LV_FS_MAX_PATH_LENGTH]; strcpy(music_dir, home_dir); strcat(music_dir, "/Music"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, music_dir); char document_dir[LV_FS_MAX_PATH_LENGTH]; strcpy(document_dir, home_dir); strcat(document_dir, "/Documents"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, document_dir); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "A:/"); #endif #endif lv_obj_add_event_cb(file_explorer, file_explorer_event_handler, LV_EVENT_ALL, NULL); #if LV_FILE_EXPLORER_QUICK_ACCESS /*Quick access status control button*/ lv_obj_t * fe_quick_access_obj = lv_file_explorer_get_quick_access_area(file_explorer); lv_obj_t * fe_header_obj = lv_file_explorer_get_header(file_explorer); lv_obj_t * btn = lv_button_create(fe_header_obj); lv_obj_set_style_radius(btn, 2, 0); lv_obj_set_style_pad_all(btn, 4, 0); lv_obj_align(btn, LV_ALIGN_LEFT_MID, 0, 0); lv_obj_add_flag(btn, LV_OBJ_FLAG_CHECKABLE); lv_obj_t * label = lv_label_create(btn); lv_label_set_text(label, LV_SYMBOL_LIST); lv_obj_center(label); lv_obj_add_event_cb(btn, btn_event_handler, LV_EVENT_VALUE_CHANGED, fe_quick_access_obj); /*Sort control*/ static const char * opts = "NONE\n" "KIND"; ``` -------------------------------- ### Arc example: create root container and slices Source: https://lvgl.io/docs/open/9.4/examples.html Sets up a flex row root container and a slices container, then creates multiple arc slices with different colors and percentages. Part of the LVGL arc example 3. ```C void lv_example_arc_3(void) { /* Root container: flex row */ lv_obj_t * root = lv_obj_create(lv_screen_active()); lv_obj_set_size(root, LV_SIZE_CONTENT, LV_SIZE_CONTENT); lv_obj_center(root); lv_obj_set_flex_flow(root, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(root, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); lv_obj_set_style_pad_all(root, 0, LV_PART_MAIN); lv_obj_set_style_border_width(root, 0, LV_PART_MAIN); lv_obj_set_style_border_color(root, lv_palette_main(LV_PALETTE_RED), LV_PART_MAIN); lv_obj_set_style_bg_opa(root, LV_OPA_TRANSP, LV_PART_MAIN); lv_obj_remove_flag(root, LV_OBJ_FLAG_SCROLLABLE); /* Slices container */ lv_obj_t * slices_container = lv_obj_create(root); lv_obj_set_size(slices_container, CHART_SIZE + 2 * SLICE_OFFSET, CHART_SIZE + 2 * SLICE_OFFSET); lv_obj_set_style_pad_all(slices_container, 0, LV_PART_MAIN); lv_obj_set_style_margin_all(slices_container, 0, LV_PART_MAIN); lv_obj_set_style_border_width(slices_container, 0, LV_PART_MAIN); lv_obj_set_style_border_color(slices_container, lv_palette_main(LV_PALETTE_BLUE), LV_PART_MAIN); lv_obj_set_style_bg_opa(slices_container, LV_OPA_TRANSP, LV_PART_MAIN); lv_obj_remove_flag(slices_container, LV_OBJ_FLAG_SCROLLABLE); /* Create slices */ angle_accum = 0.0f; create_slice(slices_container, 12, lv_palette_main(LV_PALETTE_RED)); create_slice(slices_container, 18, lv_palette_main(LV_PALETTE_BLUE)); create_slice(slices_container, 26, lv_palette_main(LV_PALETTE_GREEN)); create_slice(slices_container, 24, lv_palette_main(LV_PALETTE_ORANGE)); create_slice(slices_container, 20, lv_palette_main(LV_PALETTE_BLUE_GREY)); } #endif ``` -------------------------------- ### Size styles example (lv_example_style_1) Source: https://lvgl.io/docs/open/9.4/details/common-widget-features/styles/overview.html Shows how to use Size, Position, and Padding style properties. Sets width, height, padding, and x/y position, then applies the style to an object with a label. Requires LV_BUILD_EXAMPLES and LV_USE_IMAGE. ```C #include "../lv_examples.h" #if LV_BUILD_EXAMPLES && LV_USE_IMAGE /** * Using the Size, Position and Padding style properties */ void lv_example_style_1(void) { static lv_style_t style; lv_style_init(&style); lv_style_set_radius(&style, 5); /*Make a gradient*/ lv_style_set_width(&style, 150); lv_style_set_height(&style, LV_SIZE_CONTENT); lv_style_set_pad_ver(&style, 20); lv_style_set_pad_left(&style, 5); lv_style_set_x(&style, lv_pct(50)); lv_style_set_y(&style, 80); /*Create an object with the new style*/ lv_obj_t * obj = lv_obj_create(lv_screen_active()); lv_obj_add_style(obj, &style, 0); lv_obj_t * label = lv_label_create(obj); lv_label_set_text(label, "Hello"); } #endif ``` -------------------------------- ### Styling a bar: lv_example_bar_2 Source: https://lvgl.io/docs/open/9.4/examples.html Shows how to style a bar with custom background and indicator styles, including border, padding, radius, and animation duration. Uses lv_obj_remove_style_all for a clean start and animates the value to 100. ```C #include "../../lv_examples.h" #if LV_USE_BAR && LV_BUILD_EXAMPLES /** * Example of styling the bar */ void lv_example_bar_2(void) { static lv_style_t style_bg; static lv_style_t style_indic; lv_style_init(&style_bg); lv_style_set_border_color(&style_bg, lv_palette_main(LV_PALETTE_BLUE)); lv_style_set_border_width(&style_bg, 2); lv_style_set_pad_all(&style_bg, 6); /*To make the indicator smaller*/ lv_style_set_radius(&style_bg, 6); lv_style_set_anim_duration(&style_bg, 1000); lv_style_init(&style_indic); lv_style_set_bg_opa(&style_indic, LV_OPA_COVER); lv_style_set_bg_color(&style_indic, lv_palette_main(LV_PALETTE_BLUE)); lv_style_set_radius(&style_indic, 3); lv_obj_t * bar = lv_bar_create(lv_screen_active()); lv_obj_remove_style_all(bar); /*To have a clean start*/ lv_obj_add_style(bar, &style_bg, 0); lv_obj_add_style(bar, &style_indic, LV_PART_INDICATOR); lv_obj_set_size(bar, 200, 20); lv_obj_center(bar); lv_bar_set_value(bar, 100, LV_ANIM_ON); } #endif ``` -------------------------------- ### Compile the LVGL benchmark application Source: https://lvgl.io/docs/open/9.4/details/integration/embedded_linux/os/buildroot/quick_setup.html Compiles the lv_benchmark application using the installed SDK. The build environment is sourced from setup-build-env.sh. ```bash cd ../application/lv_benchmark source ../setup-build-env.sh cmake -B build -S . make -j $(nproc) -C build cd ../.. ``` -------------------------------- ### Simple File Explorer example (lv_example_file_explorer_1) Source: https://lvgl.io/docs/open/9.4/details/auxiliary-modules/file_explorer.html Creates a file explorer widget, sets sorting by kind, and opens a directory. Includes platform-specific paths for Windows and Linux, with optional quick access paths. Logs the selected file path on value change. ```C #include "../../lv_examples.h" #if LV_USE_TABLE && LV_USE_FILE_EXPLORER && (LV_USE_FS_STDIO || LV_USE_FS_POSIX || LV_USE_FS_WIN32 || LV_USE_FS_FATFS) && LV_BUILD_EXAMPLES #include #include static void file_explorer_event_handler(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); lv_obj_t * obj = lv_event_get_target_obj(e); if(code == LV_EVENT_VALUE_CHANGED) { const char * cur_path = lv_file_explorer_get_current_path(obj); const char * sel_fn = lv_file_explorer_get_selected_file_name(obj); LV_LOG_USER("%s%s", cur_path, sel_fn); } } void lv_example_file_explorer_1(void) { lv_obj_t * file_explorer = lv_file_explorer_create(lv_screen_active()); lv_file_explorer_set_sort(file_explorer, LV_EXPLORER_SORT_KIND); #if LV_USE_FS_WIN32 /* Note to Windows users: the initial "C:" on these paths corresponds to * the value of `LV_FS_WIN32_LETTER` in `lv_conf.h`, and should not be * confused with the Windows/DOS drive letter. It is an identifier that * is used to enable LVGL to look up the appropriate driver from a list of * registered file-system drivers. `lv_fs_win32_init()` happens to use the * identifier letter 'C' so "C:" is the driver-identifier-prefix used here. * The "C:" following that is indeed the Windows/DOS drive letter and is * part of the actual path that gets passed to the OS-level functions. * * See https://lvgl.io/docs/open/master/details/main-components/fs.html for details. * File Explorer uses `lv_fs` internally, thus the required prefix in path strings. */ lv_file_explorer_open_dir(file_explorer, "C:C:/"); #if LV_FILE_EXPLORER_QUICK_ACCESS lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, "C:C:/Users/Public/Desktop"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, "C:C:/Users/Public/Videos"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, "C:C:/Users/Public/Pictures"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, "C:C:/Users/Public/Music"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, "C:C:/Users/Public/Documents"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "C:C:/"); #endif #else /* linux */ lv_file_explorer_open_dir(file_explorer, "A:/"); #if LV_FILE_EXPLORER_QUICK_ACCESS const char * envvar = "HOME"; char home_dir[LV_FS_MAX_PATH_LENGTH]; strcpy(home_dir, "A:"); /* get the user's home directory from the HOME environment variable*/ strcat(home_dir, getenv(envvar)); LV_LOG_USER("home_dir: %s\n", home_dir); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_HOME_DIR, home_dir); char video_dir[LV_FS_MAX_PATH_LENGTH]; strcpy(video_dir, home_dir); strcat(video_dir, "/Videos"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_VIDEO_DIR, video_dir); char picture_dir[LV_FS_MAX_PATH_LENGTH]; strcpy(picture_dir, home_dir); strcat(picture_dir, "/Pictures"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_PICTURES_DIR, picture_dir); char music_dir[LV_FS_MAX_PATH_LENGTH]; strcpy(music_dir, home_dir); strcat(music_dir, "/Music"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_MUSIC_DIR, music_dir); char document_dir[LV_FS_MAX_PATH_LENGTH]; strcpy(document_dir, home_dir); strcat(document_dir, "/Documents"); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_DOCS_DIR, document_dir); lv_file_explorer_set_quick_access_path(file_explorer, LV_EXPLORER_FS_DIR, "A:/"); #endif #endif lv_obj_add_event_cb(file_explorer, file_explorer_event_handler, LV_EVENT_ALL, NULL); } #endif ``` -------------------------------- ### Make an object draggable (lv_example_obj_2) Source: https://lvgl.io/docs/open/9.4/examples.html Implements a drag event handler that moves an object based on the input device vector. The example creates a 150x100 object with a 'Drag me' label and registers the handler for LV_EVENT_PRESSING. ```C #include "../../lv_examples.h" #if LV_BUILD_EXAMPLES static void drag_event_handler(lv_event_t * e) { lv_obj_t * obj = lv_event_get_target_obj(e); lv_indev_t * indev = lv_indev_active(); if(indev == NULL) return; lv_point_t vect; lv_indev_get_vect(indev, &vect); int32_t x = lv_obj_get_x_aligned(obj) + vect.x; int32_t y = lv_obj_get_y_aligned(obj) + vect.y; lv_obj_set_pos(obj, x, y); } /** * Make an object draggable. */ void lv_example_obj_2(void) { lv_obj_t * obj; obj = lv_obj_create(lv_screen_active()); lv_obj_set_size(obj, 150, 100); lv_obj_add_event_cb(obj, drag_event_handler, LV_EVENT_PRESSING, NULL); lv_obj_t * label = lv_label_create(obj); lv_label_set_text(label, "Drag me"); lv_obj_center(label); } #endif ``` -------------------------------- ### Basic glTF Demo Setup with OpenGL ES Source: https://lvgl.io/docs/open/9.4/details/libs/gltf.html Initializes LVGL, creates a GLFW window and OpenGL ES texture, and loads a glTF demo. Uses lv_opengles_glfw_window_create, lv_opengles_texture_create, lv_opengles_texture_get_texture_id, and lv_opengles_window_add_texture. The main loop calls lv_timer_handler and delays appropriately. ```c int main(void) { /* Initialize LVGL */ lv_init(); /* GLFW setup */ lv_opengles_window_t *window = lv_opengles_glfw_window_create(WINDOW_WIDTH, WINDOW_HEIGHT, true); lv_display_t *display = lv_opengles_texture_create(WINDOW_WIDTH, WINDOW_HEIGHT); unsigned int texture_id = lv_opengles_texture_get_texture_id(display); lv_opengles_window_add_texture(window, texture_id, WINDOW_WIDTH, WINDOW_HEIGHT); /* Load and display glTF demo */ lv_demo_gltf("A:"); while (1) { uint32_t time_until_next = lv_timer_handler(); if (time_until_next == LV_NO_TIMER_READY) { time_until_next = LV_DEF_REFR_PERIOD; } lv_delay_ms(time_until_next); } return 0; } ``` -------------------------------- ### Arc example: create slice label and click event Source: https://lvgl.io/docs/open/9.4/examples.html Creates a label on an arc slice, positions it using trigonometric functions, and attaches a click event callback with slice info. Used in the LVGL arc example 3 to build interactive pie-chart slices. ```C lv_obj_t * label = lv_label_create(arc); lv_label_set_text_fmt(label, "%d%%", percentage); int mid_angle = start + ((end - start) / 2); int radius = CHART_SIZE / 4; int x_offset = (radius * lv_trigo_cos(mid_angle)) >> LV_TRIGO_SHIFT; int y_offset = (radius * lv_trigo_sin(mid_angle)) >> LV_TRIGO_SHIFT; lv_obj_align(label, LV_ALIGN_CENTER, x_offset, y_offset); slice_info_t * info = (slice_info_t *) lv_malloc(sizeof(slice_info_t)); info->start_angle = start; info->end_angle = end; info->mid_angle = mid_angle; info->out = false; info->home.x = lv_obj_get_x(arc); info->home.y = lv_obj_get_y(arc); lv_obj_add_event_cb(arc, arc_click_cb, LV_EVENT_CLICKED, info); } ``` -------------------------------- ### Install the binary into rootfs_overlay Source: https://lvgl.io/docs/open/9.4/details/integration/embedded_linux/os/buildroot/quick_setup.html Copies the compiled lvgl-app binary into the rootfs overlay so it will be included in the final image. ```bash cp application/lv_benchmark/bin/lvgl-app resources/board/rootfs_overlay/usr/bin/ ``` -------------------------------- ### Create a Hello World label (lv_example_get_started_1) Source: https://lvgl.io/docs/open/9.4/intro/getting_started/examples.html Creates a label with 'Hello world' text on the active screen and centers it. Sets the active screen's background color to 0x003a57 and the label text color to white. Requires LV_BUILD_EXAMPLES and LV_USE_LABEL to be enabled. ```C #include "../lv_examples.h" #if LV_BUILD_EXAMPLES && LV_USE_LABEL /** * Basic example to create a "Hello world" label */ void lv_example_get_started_1(void) { /*Change the active screen's background color*/ lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0x003a57), LV_PART_MAIN); /*Create a white label, set its text and align it to the center*/ lv_obj_t * label = lv_label_create(lv_screen_active()); lv_label_set_text(label, "Hello world"); lv_obj_set_style_text_color(lv_screen_active(), lv_color_hex(0xffffff), LV_PART_MAIN); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); } #endif ``` -------------------------------- ### Create animation timeline with multiple objects Source: https://lvgl.io/docs/open/9.4/examples.html Creates three objects and defines animations for a slider and each object's width and height, then adds them to an animation timeline with staggered start times. The timeline is set to maximum progress at the end. ```c /* create 3 objects */ lv_obj_t * obj1 = lv_obj_create(par); lv_obj_set_size(obj1, obj_width, obj_height); lv_obj_set_scrollbar_mode(obj1, LV_SCROLLBAR_MODE_OFF); lv_obj_t * obj2 = lv_obj_create(par); lv_obj_set_size(obj2, obj_width, obj_height); lv_obj_set_scrollbar_mode(obj2, LV_SCROLLBAR_MODE_OFF); lv_obj_t * obj3 = lv_obj_create(par); lv_obj_set_size(obj3, obj_width, obj_height); lv_obj_set_scrollbar_mode(obj3, LV_SCROLLBAR_MODE_OFF); /* anim-slider */ lv_anim_t a_slider; lv_anim_init(&a_slider); lv_anim_set_var(&a_slider, slider_prg); lv_anim_set_values(&a_slider, 0, LV_ANIM_TIMELINE_PROGRESS_MAX); lv_anim_set_custom_exec_cb(&a_slider, set_slider_value); lv_anim_set_path_cb(&a_slider, lv_anim_path_linear); lv_anim_set_duration(&a_slider, 700); /* anim-obj1 */ lv_anim_t a1; lv_anim_init(&a1); lv_anim_set_var(&a1, obj1); lv_anim_set_values(&a1, 0, obj_width); lv_anim_set_custom_exec_cb(&a1, set_width); lv_anim_set_path_cb(&a1, lv_anim_path_overshoot); lv_anim_set_duration(&a1, 300); lv_anim_t a2; lv_anim_init(&a2); lv_anim_set_var(&a2, obj1); lv_anim_set_values(&a2, 0, obj_height); lv_anim_set_custom_exec_cb(&a2, set_height); lv_anim_set_path_cb(&a2, lv_anim_path_ease_out); lv_anim_set_duration(&a2, 300); /* anim-obj2 */ lv_anim_t a3; lv_anim_init(&a3); lv_anim_set_var(&a3, obj2); lv_anim_set_values(&a3, 0, obj_width); lv_anim_set_custom_exec_cb(&a3, set_width); lv_anim_set_path_cb(&a3, lv_anim_path_overshoot); lv_anim_set_duration(&a3, 300); lv_anim_t a4; lv_anim_init(&a4); lv_anim_set_var(&a4, obj2); lv_anim_set_values(&a4, 0, obj_height); lv_anim_set_custom_exec_cb(&a4, set_height); lv_anim_set_path_cb(&a4, lv_anim_path_ease_out); lv_anim_set_duration(&a4, 300); /* anim-obj3 */ lv_anim_t a5; lv_anim_init(&a5); lv_anim_set_var(&a5, obj3); lv_anim_set_values(&a5, 0, obj_width); lv_anim_set_custom_exec_cb(&a5, set_width); lv_anim_set_path_cb(&a5, lv_anim_path_overshoot); lv_anim_set_duration(&a5, 300); lv_anim_t a6; lv_anim_init(&a6); lv_anim_set_var(&a6, obj3); lv_anim_set_values(&a6, 0, obj_height); lv_anim_set_custom_exec_cb(&a6, set_height); lv_anim_set_path_cb(&a6, lv_anim_path_ease_out); lv_anim_set_duration(&a6, 300); /* add animations to timeline */ lv_anim_timeline_add(anim_timeline, 0, &a_slider); lv_anim_timeline_add(anim_timeline, 0, &a1); lv_anim_timeline_add(anim_timeline, 0, &a2); lv_anim_timeline_add(anim_timeline, 200, &a3); lv_anim_timeline_add(anim_timeline, 200, &a4); lv_anim_timeline_add(anim_timeline, 400, &a5); lv_anim_timeline_add(anim_timeline, 400, &a6); lv_anim_timeline_set_progress(anim_timeline, LV_ANIM_TIMELINE_PROGRESS_MAX); } #endif ``` -------------------------------- ### Install WSL Source: https://lvgl.io/docs/open/9.4/details/xml/editor/install.html If WSL is not installed, run this command to install it. ```bash wsl --install ```