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

相关推荐
Lhan.zzZ5 分钟前
笔记_2026.4.28_004
c++·ide·笔记·qt
云水一下1 小时前
从零开始!VMware安装Fedora Workstation 44桌面系统完整教程
前端
小码哥_常2 小时前
安卓黑科技:实现多平台商品详情页一键跳转APP
前端
Deitymoon2 小时前
STM32——蓝牙模块双串口控制led
stm32·单片机·嵌入式硬件
killerbasd2 小时前
还是迷茫 5.3
前端·react.js·前端框架
其实防守也摸鱼2 小时前
CTF密码学综合教学指南--第五章
开发语言·网络·笔记·python·安全·网络安全·密码学
不会敲代码13 小时前
TCP/IP 与前端性能:从数据包到首次渲染的底层逻辑
前端·tcp/ip
kyriewen3 小时前
奥特曼借GPT-5.5干杯,而你的Copilot正按Token收钱
前端·github·openai
AC赳赳老秦3 小时前
投标合规提效:用 OpenClaw 实现标书 / 合同自动审核、关键词校验、格式优化,降低废标风险
开发语言·前端·python·eclipse·emacs·deepseek·openclaw
kyriewen3 小时前
代码写成一锅粥?3个设计模式让你的项目“起死回生”
前端·javascript·设计模式