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,下一篇我们将继续优化界面,为按钮和界面增加图标显示,让界面更美观,敬请关注!

相关推荐
呃呃呃呃ex10 分钟前
2026年古法编程的末法时代,如何评估自己完成迅速转行
前端·后端
南京兴帝文化传媒有限公司12 分钟前
地图SEO与AI搜索优化结合实践:宁国摄影工作室本地获客案例分析
大数据·前端·人工智能·geo 优化·geo优化避坑
youcans_17 分钟前
【嵌入式软件AI编程】08. 第一个STM32工程
stm32·单片机·ai编程·嵌入式软件·claude code
用户9210802628619 分钟前
前端 Vue 专栏 07:模板编译、虚拟 DOM、Diff 与 key
前端
光影少年22 分钟前
react navite process.nextTick 和 Promise.then 的执行顺序
前端·react native·react.js
雪芽蓝域zzs24 分钟前
第四十二节:全局字典封装(后端字典,下拉选择复用)
开发语言·前端·javascript
用户645965987108826 分钟前
Nginx + Vue Router 基础:SPA History 部署、反向代理与请求分流
前端
样子201826 分钟前
Js 之根据白名单过滤 HTML(防止 XSS 攻击)
android·前端·javascript·html·xss
lewis_lk28 分钟前
ReactJs状态迷思:从"常量"到"闭包陷阱"的底层逻辑
前端·react.js
kaixin_啊啊29 分钟前
中国研究生数学建模竞赛(华为杯)学习笔记——三维瀑布图绘图代码
笔记·学习·数学建模