LVGL 시뮬레이터에서 내가 만든 UI 코드 실행하기

lvgl

LVGL PC 시뮬레이터가 제공하는 기본 화면(lv_demo_widgets())은 기능은 충분하지만, 실제 프로젝트를 빠르게 익히기엔 기본 설정이 과하게 느껴질 수 있다. 그래서 src/main.c 안에서 데모를 주석 처리하고, 내가 만든 위젯을 직접 추가하여 LVGL을 학습하기 쉽게 하였다.

1. Custom widget을 추가한 이유?

기존 데모는 처음 LVGL을 배우는 사람에게 좀 과하고, 분석하고 테스트해보기 쉽지는 않아보인다. 기본 샘플을 미리 테스트해보기 위해 기존 UI를 비활성화하고, 기본 코드를 렌더링하는 커스텀 위젯을 추가하였다.

2. 커스텀 위젯 추가 방법

src/main.c에 아래와 같이 create_custom_ui() 함수를 추가한다. 그리고 기존 위젯을 보여주는 코드인 lv_demo_widgets()를 주석 처리한다.

그럼 내가 추가한 위젯이 시뮬레이터에서 보인다.

렌더링해보고 싶은 코드를 커스텀 위젯 함수 안에 넣고, 빌드해서 실행해보면 된다.

3. 기본 샘플 코드 설명

다음 함수는 lv_scr_load로 새 스크린을 만들고, 가운데 정렬된 패널 안에 텍스트, 진행률 표시, 슬라이더, 버튼을 넣는다. 그리고 각 요소에 여백과 너비를 지정한다.

/* src/main.c */
static void create_custom_ui(void)
{
  lv_obj_t *scr = lv_obj_create(NULL);
  lv_obj_clear_flag(scr, LV_OBJ_FLAG_SCROLLABLE);
  lv_scr_load(scr);

  lv_obj_t *panel = lv_obj_create(scr);
  lv_obj_set_size(panel, 360, 240);
  lv_obj_align(panel, LV_ALIGN_CENTER, 0, 0);
  lv_obj_set_style_radius(panel, 18, 0);
  lv_obj_set_style_pad_all(panel, 16, 0);

  lv_obj_t *title = lv_label_create(panel);
  lv_label_set_text(title, "My Custom Widget");
  lv_obj_set_style_text_font(title, &lv_font_montserrat_20, 0);
  lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 0);

  lv_obj_t *status = lv_label_create(panel);
  lv_label_set_text(status, "Default UI ready");
  lv_obj_align_to(status, title, LV_ALIGN_OUT_BOTTOM_MID, 0, 6);

  lv_obj_t *bar = lv_bar_create(panel);
  lv_obj_set_width(bar, 280);
  lv_bar_set_value(bar, 64, LV_ANIM_OFF);
  lv_obj_align_to(bar, status, LV_ALIGN_OUT_BOTTOM_MID, 0, 18);
  lv_obj_set_style_radius(bar, 8, LV_PART_MAIN);
  lv_obj_set_style_pad_row(bar, 12, LV_PART_MAIN);

  lv_obj_t *slider = lv_slider_create(panel);
  lv_slider_set_value(slider, 30, LV_ANIM_OFF);
  lv_obj_set_width(slider, 280);
  lv_obj_align_to(slider, bar, LV_ALIGN_OUT_BOTTOM_MID, 0, 24);

  lv_obj_t *btn = lv_btn_create(panel);
  lv_obj_set_size(btn, 140, 50);
  lv_obj_align(btn, LV_ALIGN_BOTTOM_MID, 0, -8);
  lv_obj_t *btn_label = lv_label_create(btn);
  lv_label_set_text(btn_label, "Run Action");
}

main()에서 기존 lv_demo_widgets() 호출을 주석 처리하고 create_custom_ui()를 호출하면, 위 함수가 맨 처음 로딩되는 화면이 된다. 이렇게 직접 만든 패널에 새 위젯을 추가하거나 현재 요소를 수정하며 즉시 결과를 확인하는 흐름이 가능하다.

4. 실행 화면

시뮬레이터 실행
시뮬레이터 실행

5. 전체 코드 diff

전체 코드 변경 사항은 아래와 같다. 참고하실 분은 참고하세요.

diff --git a/src/main.c b/src/main.c
index c893220..c192c34 100644
--- a/src/main.c
+++ b/src/main.c
@@ -26,6 +26,8 @@
 
 #include "hal/hal.h"
 
+static void create_custom_ui(void);
+
 /*********************
  *      DEFINES
  *********************/
@@ -69,14 +71,15 @@ int main(int argc, char **argv)
   /* - lv_demo_stress(); */
   /* - lv_example_label_1(); */
   /* - etc. */
-  lv_demo_widgets();
+  /* lv_demo_widgets(); */
+  create_custom_ui();
 
   while(1) {
     /* Periodically call the lv_task handler.
      * It could be done in a timer interrupt or an OS task too.*/
     uint32_t sleep_time_ms = lv_timer_handler();
     if(sleep_time_ms == LV_NO_TIMER_READY){
-       sleep_time_ms =  LV_DEF_REFR_PERIOD;
+        sleep_time_ms =  LV_DEF_REFR_PERIOD;
     }
 #ifdef _MSC_VER
     Sleep(sleep_time_ms);
@@ -88,10 +91,49 @@ int main(int argc, char **argv)
   return 0;
 }
 
+static void create_custom_ui(void)
+{
+  lv_obj_t *scr = lv_obj_create(NULL);
+  lv_obj_clear_flag(scr, LV_OBJ_FLAG_SCROLLABLE);
+  lv_scr_load(scr);
+
+  lv_obj_t *panel = lv_obj_create(scr);
+  lv_obj_set_size(panel, 360, 240);
+  lv_obj_align(panel, LV_ALIGN_CENTER, 0, 0);
+  lv_obj_set_style_radius(panel, 18, 0);
+  lv_obj_set_style_pad_all(panel, 16, 0);
+
+  lv_obj_t *title = lv_label_create(panel);
+  lv_label_set_text(title, "My Custom Widget");
+  lv_obj_set_style_text_font(title, &lv_font_montserrat_20, 0);
+  lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 0);
+
+  lv_obj_t *status = lv_label_create(panel);
+  lv_label_set_text(status, "Default UI ready");
+  lv_obj_align_to(status, title, LV_ALIGN_OUT_BOTTOM_MID, 0, 6);
+
+  lv_obj_t *bar = lv_bar_create(panel);
+  lv_obj_set_width(bar, 280);
+  lv_bar_set_value(bar, 64, LV_ANIM_OFF);
+  lv_obj_align_to(bar, status, LV_ALIGN_OUT_BOTTOM_MID, 0, 18);
+  lv_obj_set_style_radius(bar, 8, LV_PART_MAIN);
+  lv_obj_set_style_pad_row(bar, 12, LV_PART_MAIN);
+
+  lv_obj_t *slider = lv_slider_create(panel);
+  lv_slider_set_value(slider, 30, LV_ANIM_OFF);
+  lv_obj_set_width(slider, 280);
+  lv_obj_align_to(slider, bar, LV_ALIGN_OUT_BOTTOM_MID, 0, 24);
+
+  lv_obj_t *btn = lv_btn_create(panel);
+  lv_obj_set_size(btn, 140, 50);
+  lv_obj_align(btn, LV_ALIGN_BOTTOM_MID, 0, -8);
+  lv_obj_t *btn_label = lv_label_create(btn);
+  lv_label_set_text(btn_label, "Run Action");
+}
 
 #endif

Related Posts