LVGL 入门(十五):接口优化

目录


一、前言

我是 Hello_Embed

在上一篇笔记中,我们通过结构体封装界面接口,实现了规范化的多界面管理。但代码中还存在判断逻辑繁琐按钮创建代码重复的问题,同时我们也可以为界面增加定时器功能,完善交互体验。本篇将对界面接口进行全面优化,简化判断逻辑、消除冗余代码,并为界面集成定时器功能。


二、判断逻辑优化

原始的界面切换判断通过字符串对比实现,代码冗余且不简洁:

c 复制代码
    if(strcmp(lv_label_get_text(label), "Page[1]") == 0)
    {
        lv_my_ui_page1_t.open();
    }
    if(strcmp(lv_label_get_text(label), "Page[2]") == 0)
    {
        lv_my_ui_page2_t.open();
    }

优化思路

利用 LVGL 对象的用户数据功能,将界面结构体直接绑定到按钮上,无需字符串判断,直接调用接口。

  1. 创建按钮时,绑定对应的界面结构体:
c 复制代码
    //界面1
    btn = lv_btn_create(g_page_cont);
    lv_obj_align(btn, LV_ALIGN_CENTER, 0, 20);
    lv_obj_set_user_data(btn, &lv_my_ui_page1_t);
    label = lv_label_create(btn);
    lv_label_set_text(label, "Page[1]");
    lv_obj_center(label);
    lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, label);

    //界面2
    btn = lv_btn_create(g_page_cont);
    lv_obj_align(btn, LV_ALIGN_CENTER, 0, 60);
    lv_obj_set_user_data(btn, &lv_my_ui_page2_t);
    label = lv_label_create(btn);
    lv_label_set_text(label, "Page[2]");
    lv_obj_center(label);
  1. 事件回调中直接获取结构体并打开界面:
c 复制代码
static void event_handler(lv_event_t * e)
{
    lv_obj_t * btn = lv_event_get_target(e);
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * label = lv_event_get_user_data(e);

    lv_obj_t * page_cont = lv_obj_get_parent(btn);

    lv_my_ui_page_data_t * page_data = lv_obj_get_user_data(btn);

    if(code == LV_EVENT_CLICKED) {
        LV_LOG_USER("%s", lv_label_get_text(label));

        page_data->open();

        lv_obj_add_flag(page_cont, LV_OBJ_FLAG_HIDDEN);
    }
}

三、重复代码优化

主界面中两个按钮的创建代码高度重复,进一步优化:

使用结构体数组 存储界面数据,通过for循环批量创建按钮,配合宏定义防止数组越界。

优化后代码:

c 复制代码
#define LIST_NUM 2

void my_ui_main_init(void)
{
    g_page_cont = lv_button_create(lv_screen_active());
    lv_obj_set_size(g_page_cont, lv_pct(100), lv_pct(100));
    lv_obj_set_style_bg_color(g_page_cont, lv_color_hex(0x00ff00), 0);

    lv_obj_t * label;
    lv_obj_t * btn;

    for(uint16_t index = 0; index < LIST_NUM; index++)
    {
        btn = lv_btn_create(g_page_cont);
        lv_obj_set_user_data(btn, g_page_list[index]);
        lv_obj_align(btn, LV_ALIGN_TOP_MID, index * 100, 20);

        label = lv_label_create(btn);
        lv_label_set_text_fmt(label, "Page[%d]", index + 1);
        lv_obj_center(label);

        lv_obj_add_event_cb(btn, event_handler, LV_EVENT_CLICKED, label);
    }
}

四、界面定时器功能引入

为界面 1 添加定时器功能,实现实时计时显示后台日志打印,切换界面时正常管理定时器。

c 复制代码
static uint16_t page_open(void)
{
    lv_obj_t * page_cont = lv_obj_create(lv_screen_active());
    lv_obj_set_size(page_cont, LV_PCT(100), LV_PCT(100));
    lv_obj_set_style_bg_color(page_cont, lv_color_hex(0x00ff00), 0);

    lv_obj_t * btn = lv_button_create(page_cont);
    lv_obj_align(btn, LV_ALIGN_CENTER, 0, 0);

    lv_obj_t * label = lv_label_create(btn);
    lv_label_set_text(label, "Page[1]");
    lv_obj_center(label);

    lv_obj_add_event_cb(btn, page_close_event_handler, LV_EVENT_CLICKED, page_cont);

    label = lv_label_create(page_cont);
    lv_obj_set_style_text_font(label, &lv_font_montserrat_20, 0);
    lv_label_set_text_fmt(label, "Timer: %d", 0);

    lv_timer_t * timer = lv_timer_create(page_timer, 1000, label);
    lv_obj_set_user_data(page_cont, timer);

    lv_my_ui_page1_t.page_cont = page_cont;

    return 0;
}

static void page_timer(lv_timer_t * timer)
{
    lv_obj_t * label = lv_timer_get_user_data(timer);
    static int count = 0;
    count++;
    lv_label_set_text_fmt(label, "Timer: %d", count);
    LV_LOG_USER("%s %d", lv_label_get_text(label), count);
}

主界面运行效果:

界面 1 显示与后台日志效果:


五、总结

  1. 通过对象用户数据绑定结构体,消除字符串判断,简化界面切换逻辑;
  2. 采用循环 + 数组批量创建按钮,解决代码重复问题,提升可扩展性;
  3. 为界面集成定时器功能,实现计时显示与后台打印,完善功能交互。

六、结尾

本次优化让界面接口架构更简洁、扩展性更强,同时完成了定时器功能的集成。我是 Hello_Embed,下一篇我们将继续优化界面,为按钮和界面增加图标显示,让界面更美观,敬请关注!

相关推荐
孞㐑¥2 小时前
算法—记忆化搜索
开发语言·c++·经验分享·笔记·算法
chushiyunen2 小时前
人工智能-语义校验deepEval笔记
人工智能·笔记
hssfscv2 小时前
软件设计师下午题二 E-R图
java·笔记·学习
lpfasd1232 小时前
2026年第12周社区趋势周报
笔记
huabiangaozhi2 小时前
spring-boot-starter和spring-boot-starter-web的关联
前端
umeelove352 小时前
Spring boot整合quartz方法
java·前端·spring boot
小码哥_常2 小时前
Android 开发探秘:View.post()为何能获取View宽高
前端
爱学习的程序媛2 小时前
【Web前端】WebAssembly详解
前端·web·wasm
RSFeegg2 小时前
【AI Agent 学习笔记task2】Day3 Hello-Agents 第二章:智能体发展史深度解读
人工智能·笔记·学习