【Lvgl】 对象、控件与交互事件解析
本文最后更新于48 天前,其中的信息可能已经过时,如有错误请发送邮件到tudougin@163.com

1. LVGL 对象系统(Object System)

​ LVGL 中几乎所有的 UI 元素都是从 lv_obj_t 派生的对象,遵循“组件 + 样式 +事件” 的思想,以下是官方的例程。

image-20250709230734582
void lv_say_hello(void)
{
    // 获取当前活动屏幕对象
    lv_obj_t * scr = lv_scr_act(); // lv_scr_act 是 LVGL 8.x 的推荐用法

    // 设置屏幕背景颜色为深蓝色
    lv_obj_set_style_bg_color(scr, lv_color_hex(0x003a57), LV_PART_MAIN);

    // 创建标签对象并设置基本属性
    lv_obj_t * label = lv_label_create(scr); // 父对象为屏幕
    lv_label_set_text(label, "Hello world"); // 设置文本内容
    lv_obj_set_style_text_color(label, lv_color_hex(0xffffff), LV_PART_MAIN); // 设置文字颜色为白色

    // 设置字体(可选,如果有自定义字体)
    // lv_obj_set_style_text_font(label, &your_font, LV_PART_MAIN);

    // 对齐标签到屏幕中心
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
}

1.1 对象的基本概念

    lv_obj_t * label = lv_label_create(scr); //以屏幕为父对象创建对象
    lv_label_set_text(label, "Hello world"); // 设置文本内容
  • 每个控件都是一个对象,基类是 lv_obj_t
  • 创建对象时用 lv_obj_create()lv_xxx_create()(比如 lv_label_create()
  • 对象树结构:对象之间有父子关系,便于分层管理和事件传播

1.2 对象的属性设置

    lv_obj_set_style_text_color(label, lv_color_hex(0xffffff), LV_PART_MAIN); // 设置文字颜色为白色
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
  • 设置大小:lv_obj_set_size(obj, w, h)
  • 设置位置:lv_obj_set_pos(obj, x, y)
  • 设置对齐:lv_obj_align(obj, LV_ALIGN_CENTER, x_ofs, y_ofs)
  • 设置样式:lv_obj_add_style(obj, &style, part)

1.3 样式系统(Style)

    lv_obj_set_style_text_color(label, lv_color_hex(0xffffff), LV_PART_MAIN); // 设置文字颜色为白色
    // lv_obj_set_style_text_font(label, &your_font, LV_PART_MAIN);
  • lv_style_t 是样式的核心结构体,可以定义颜色、边框、阴影、字体等

2. 常用控件(Widgets)

LVGL 提供了丰富的控件,以下是一些最常用的控件:

控件描述常用函数
Label显示文本lv_label_create(), lv_label_set_text()
Button按钮控件lv_btn_create(), lv_obj_add_event_cb()
Slider滑条控件lv_slider_create(), lv_slider_get_value()
Switch开关lv_switch_create()
Chart图表控件lv_chart_create(), lv_chart_set_next_value()
Textarea文本输入框lv_textarea_create(), lv_textarea_set_text()
Dropdown下拉框lv_dropdown_create(), lv_dropdown_set_options()
Checkbox复选框lv_checkbox_create(), lv_checkbox_is_checked()

2.1 按键

按钮(lv_btn)是一个标准可交互控件,常用于执行点击行为、触发回调、配合标签显示文字等。

image-20250713224648087
功能特性描述
点击交互支持触控设备点击(触摸)、模拟点击(lv_event_send
事件驱动可绑定多个事件,如 LV_EVENT_CLICKEDLV_EVENT_PRESSEDLV_EVENT_RELEASED
状态响应自动切换不同状态样式,如按下状态、不可用状态等
可嵌套控件可放入标签、图标、图片、甚至其他按钮(嵌套)
动画和过渡LVGL 可通过 style transition 实现点击过渡动画

测试代码:

// 全局变量保存按钮对象
static lv_obj_t * btn_global = NULL;

/**
 * 按钮事件回调:点击后更新文字计数
 */
static void btn_event_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * btn = lv_event_get_target(e);

    if(code == LV_EVENT_CLICKED) {
        static uint8_t cnt = 0;
        cnt++;

        lv_obj_t * label = lv_obj_get_child(btn, 0);
        lv_label_set_text_fmt(label, "Button: %d", cnt);
    }
}

/**
 * 定时器回调函数:模拟点击按钮
 */
static void timer_cb(lv_timer_t * timer)
{
    ESP_LOGI(TAG, "定时器回调函数:模拟点击按钮");
    if(btn_global) {
        lv_event_send(btn_global, LV_EVENT_CLICKED, NULL);  // 触发点击事件
    }
}

/**
 * 创建按钮及标签
 */
void lv_set_btn(void)
{
    lv_obj_t * btn = lv_btn_create(lv_scr_act()); 
    lv_obj_set_pos(btn, 10, 10);
    lv_obj_set_size(btn, 120, 50);
    lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL);

    lv_obj_t * label = lv_label_create(btn);
    lv_label_set_text(label, "Button");
    lv_obj_center(label);

    // ✅ 保存按钮指针,供定时器使用
    btn_global = btn;
}

/**
 * 主程序入口
 */
void app_main(void) {
    ESP_LOGI(TAG, "程序启动");

    lvgl_mutex = xSemaphoreCreateMutex();
    assert(lvgl_mutex != NULL);

    vTaskDelay(pdMS_TO_TICKS(1000));
    spi_master_init();

    lvgl_tick_timer_init();
    lv_port_disp_init();

    xTaskCreate(lvgl_task, "lvgl_task", 4096, NULL, 5, NULL);

    vTaskDelay(pdMS_TO_TICKS(200));
    lv_set_btn();

    // ✅ 正确创建 LVGL 定时器(自动每 1000ms 执行一次 timer_cb)
    lv_timer_create(timer_cb, 1000, NULL);

    // 空循环,不再手动调用 timer_cb
    while (1) {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

示例代码中按钮支持的特性:

  • 创建后自动显示
  • 可以响应用户点击或程序模拟事件
  • 内部嵌套一个标签,并动态更新其文本
  • 样式跟随状态改变,如点击时变暗

2.2 滑条

滑条(又叫滑块、滑动条、进度条控件)是图形界面中一种可视化的数值调节控件,用户可以通过拖动滑块改变其数值。

image-20250712145757321
特性描述
支持范围可设置最小值和最大值(比如 0 ~ 100)
显示当前值可通过标签显示滑块的当前值
双向交互用户可以拖动它,也可以由程序代码控制它
事件响应每次用户拖动都会触发 LV_EVENT_VALUE_CHANGED 事件
可自定义样式可以设置颜色、高度、圆角、指示条样式等
动画支持可使用动画让滑块平滑地变化而不是跳变

测试代码:

static lv_obj_t * label_slider = NULL;
static lv_obj_t * slider_global = NULL;  // 用于程序控制滑块

/**
 * 滑块事件回调:当滑块值变化时更新标签
 */
static void slider_event_cb(lv_event_t * e)
{
    lv_obj_t * slider = lv_event_get_target(e);
    lv_label_set_text_fmt(label_slider, "%" LV_PRId32, lv_slider_get_value(slider));
    lv_obj_align_to(label_slider, slider, LV_ALIGN_OUT_TOP_MID, 0, -15);
}

/**
 * 创建滑块与标签
 */
void lv_set_slider(void)
{
    lv_obj_t * slider = lv_slider_create(lv_scr_act());
    lv_obj_set_width(slider, 120);
    lv_obj_set_pos(slider, 20, 50);
    lv_obj_add_event_cb(slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
    lv_slider_set_range(slider, 0, 100);
    lv_slider_set_value(slider, 50, LV_ANIM_OFF);

    // 保存到全局变量
    slider_global = slider;

    label_slider = lv_label_create(lv_scr_act());
    lv_label_set_text(label_slider, "50");
    lv_obj_align_to(label_slider, slider, LV_ALIGN_OUT_TOP_MID, 0, -15);
}

void update_slider_value(int32_t val)
{
    if (slider_global) {
        lv_slider_set_value(slider_global, val, LV_ANIM_ON);
        lv_event_send(slider_global, LV_EVENT_VALUE_CHANGED, NULL);
    }
}

static void slider_auto_inc_cb(lv_timer_t * timer)
{
    static int32_t val = 50;
    val++;
    if(val > 100) val = 0;
    update_slider_value(val);
}

示例代码中按钮支持的特性:

  • 创建后立即显示在屏幕上
  • 支持用户拖动改变数值
  • 支持程序主动设置值,含动画效果
  • 值变化时触发事件回调
  • 可联动标签实时显示当前值
  • 可通过定时器自动更新数值
  • 支持灵活对齐布局与样式自定义

3. 事件机制

​ LVGL 在对象的生命周期或用户交互时,自动检测状态变化并发送对应事件。事件机制是Lvgl UI 交互的核心之一,它允许程序监听并响应各种用户操作(比如点击、拖动、值改变),或者对象状态变化(比如创建、删除等)。LVGL 中所有对象都可以接收事件,事件通过回调函数处理:

  • 事件类型: 每种事件对应 lv_event_code_t 枚举,如 LV_EVENT_CLICKED, LV_EVENT_VALUE_CHANGED 等。
  • 事件函数: 格式固定 void callback(lv_event_t * e)
  • 事件对象: 可以通过 lv_event_get_target(e) 获取触发事件的对象。

3.1 常见的事件类型(lv_event_code_t)

完整事件列表见:lv_event.h

事件代码触发时机常见控件
LV_EVENT_CLICKED被点击时按钮、图片等
LV_EVENT_PRESSED按下(触摸)按钮、滑块
LV_EVENT_RELEASED释放(触摸结束)按钮
LV_EVENT_VALUE_CHANGED值改变(如 slider)滑块、开关、下拉框
LV_EVENT_FOCUSED / LV_EVENT_DEFOCUSED获取/失去焦点文本输入框等
LV_EVENT_DRAW_MAIN_BEGIN/END绘制开始/结束高级自定义绘图用
LV_EVENT_DELETE对象被删除时所有对象

3.2 使用流程

2.1按键中的代码为例:

3.2.1 编写事件回调函数

void btn_event_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * btn = lv_event_get_target(e);

    if(code == LV_EVENT_CLICKED) {
        static uint8_t cnt = 0;
        cnt++;

        lv_obj_t * label = lv_obj_get_child(btn, 0);
        lv_label_set_text_fmt(label, "Button: %d", cnt);
    }
}
  • 通过 lv_event_get_code 判断事件类型,通过 lv_event_get_target 知道是哪个对象触发了事件。
  • 这段代码只对 LV_EVENT_CLICKED 类型作出响应,展示了事件机制的基本用法。

3.2.2 将事件回调绑定对象

这段代码创建了一个带标签的按钮,并将事件回调函数绑定到该按钮上,以响应所有类型的事件。

void lv_set_btn(void)
{
    lv_obj_t * btn = lv_btn_create(lv_scr_act()); 
    lv_obj_set_pos(btn, 10, 10);
    lv_obj_set_size(btn, 120, 50);
    lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL);

    lv_obj_t * label = lv_label_create(btn);
    lv_label_set_text(label, "Button");
    lv_obj_center(label);

    // ✅ 保存按钮指针,供定时器使用
    btn_global = btn;
}

绑定事件回调函数:

lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL);

这是事件机制的重点,含义如下:

  • btn: 绑定事件的目标对象 —— 这个按钮。
  • btn_event_cb: 回调函数 —— 触发事件时调用的函数(你上面定义的)。
  • LV_EVENT_ALL: 指定接收所有事件类型(包括 CLICKED, PRESSED 等等)。(也可以换成具体事件类型,比如 LV_EVENT_CLICKED,只响应点击事件)
  • NULL: 用户数据(user_data),此处没有使用。

3.3 模拟触发事件

​ 这段代码通过定时器回调函数,使用 lv_event_send 主动触发按钮的 LV_EVENT_CLICKED 事件,实现了模拟点击行为,从而调用绑定的事件回调函数。

void timer_cb(lv_timer_t * timer)
{
    ESP_LOGI(TAG, "定时器回调函数:模拟点击按钮");
    if(btn_global) {
        lv_event_send(btn_global, LV_EVENT_CLICKED, NULL);  // 触发点击事件
    }
}
  • 使用 lv_event_send 向按钮手动发送一个 LV_EVENT_CLICKED 事件。
  • 这会使之前绑定到按钮的回调函数 btn_event_cb() 被调用,就好像用户实际点击了按钮一样。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇