LVGL

LVGL

一、概念

LVGL(Light and Versatile Graphics Library) 是一个开源的嵌入式 GUI(图形用户界面)库,专门用于 小型 MCU/MPU 的显示屏开发,比如 STM32、ESP32、NXP i.MX 等。它特点是轻量、移植灵活、功能丰富。

LVGL 所有的对象都在lv_obj_t结构体进行变化。

在这里插入图片描述

lv_obj_t结构体:

typedef struct _lv_obj_t {
    const lv_obj_class_t * class_p;
    struct _lv_obj_t * parent;
    _lv_obj_spec_attr_t * spec_attr;
    _lv_obj_style_t * styles;
#if LV_USE_USER_DATA
    void * user_data;
#endif
    lv_area_t coords;
    lv_obj_flag_t flags;
    lv_state_t state;
    uint16_t layout_inv : 1;
    uint16_t readjust_scroll_after_layout : 1;
    uint16_t scr_layout_inv : 1;
    uint16_t skip_trans : 1;
    uint16_t style_cnt  : 6;
    uint16_t h_layout   : 1;
    uint16_t w_layout   : 1;
    uint16_t being_deleted   : 1;
} lv_obj_t;

二、对象

在 LVGL 中,一切界面元素都是对象(lv_obj_t),对象是 GUI 系统的核心概念。理解对象的结构和特性,才能真正掌握 LVGL 的使用方法。

创建对象时候,首先要创建一个父类,这个父类有两种

  1. 直接使用活动屏幕创建,对象的父类是活动屏幕
  2. 使用对象A创建,创建后,新的对象B是对象A的子类

2.1 父对象与子对象的关系

  • 子对象默认是在父对象的左上角创建
  • 子对象会随着父对象移动
  • 子对象位置超出父对象范围,超出部分不显示

2.2 基础对象

创建基础对象

lv_obj_t* obj1 = lv_obj_create(lv_src_act()); 
  • lv_scr_act() 获取活动屏幕
  • lv_obj_set_size(对象, w, h) 设置对象大小
  • lv_obj_set_pos(对象, x, y) 设置位置

三、 部件

3.1 部件的创建

lv_部件名_create();

例如:创建一个开关

lv_swtich_create();

3.2 lv_obj部件

  • lv_obj基础对象,相当于 LVGL 的“容器”。
  • 其他所有控件(如按钮 lv_btn、标签 lv_label、开关 lv_switch 等)都是基于 lv_obj 扩展的。
  • 你可以单独使用 lv_obj 来创建一个矩形区域,用于显示颜色、作为容器或作为布局的父对象。

3.3 lv_label 标签部件

标签组成部分:

  • 主体 LV_PART_MAIN
  • 滚动条 LV_PART_SCROLLBAR
  • 选中的文本 LV_PART_SELECTED
3.3.1 创建标签部件
lv_obj_t* label = lv_label_create(parent);
3.3.1.1 设置标签文本

存储文本的内存动态分配

lv_label_set_text(部件名,"文本内容");

存储文本在指定的缓冲区中

lv_label_set_text_static(部件名,"文本内容");

由于存储的区域是代码段,只读。后面如果发生更改就会报错。

格式化显示文本

lv_label_set_text_fmt(部件名, "内容 %d",10);  // 后面内容部分就类似printf一样,有占位符
3.3.2 设置标签样式
3.3.2.1 背景颜色
lv_obj_set_style_bg_color(部件名, 颜色, 选择器);

标签的背景颜色透明度默认是透明的,所以单独设置背景颜色看起来是没有生效的。

lv_obj_set_style_bg_opa(部件名, 透明度 ,选择器); // 透明度范围是 0~255

通过这个修改透明度就可以显示背景颜色了。

3.3.2.2 字体大小
lv_obj_set_style_text_font(部件名, 字体, 选择器);

lv.conf.h 里面有字体的宏,使用前需要将宏置1。

在这里插入图片描述

3.3.2.3 文本颜色
lv_obj_set_style_text_color(部件名, 颜色, 选择器);
3.3.2.4 设置个别文本的字体颜色
lv_label_set_recolor(部件名, true); // 开启重新着色功能
lv_label_set_text(部件名, "文本信息1 #ff0000 文本信息2 #  "); 
3.3.5 文本阴影

多复制一份文本,颜色调淡,偏移一定位置。

3.4 长文本模式(长模式)
  • 默认情况下,如果没有限定标签部件大小,标签大小自动为文本大小。
  • 长文本模式是可以手动修改文本显示模式

在这里插入图片描述

lv_label_set_long_mode(label, LV_LABEL_LONG_...);

在按钮里显示标签信息

在这里插入图片描述

#ff0000 文本 # 可以自定义颜色


3.4 lv_but 按钮部件

3.4.1 创建按钮部件
lv_obj_t* btn = lv_btn_create(parent);
3.4.2 设置样式
lv_obj_set_size( btn, 100, 50 );
lv_obj_set_align( btn, LV_ALIGN_CENTER );
lv_obj_set_style_bg_color( btn,lv_color_hex(Oxffe1d4), LV_STATE_PRESSED );
3.4.3 添加事件

按钮状态切换

lv_obj_add_flag( btn, LV_OBJ_FLAG_CHECKABLE );

监测事件值发生的变化

lv_obj_add_event_cb( btn, event_cb,LV_EVENT_VALUE_CHANGED,NULL );

3.5 lv_switch 按钮部件

组成部分:

  • 主体 LV_PART_MAIN
  • 手柄 LV_PART_KNOB
  • 指示器 LV_PART_INDICATOR
3.5.1 创建开关部件
lv_obj_t* switch1 = lv_swtich_create(parent);
3.5.2 设置样式

设置手柄颜色

lv_obj_set_style_bg_color( switch1,lv_color_hex(Oxffe1d4), LV_PART_KNOB);

设置指示器颜色

    lv_obj_set_style_bg_color( switch1,lv_color_hex(Oxffe1d4), LV_PART_INDICARTOR);

直接设置发现貌似没有被更改。其实是已经更改了,不过开关默认是关闭的导致颜色被覆盖。

3.5.3 添加、清除开关状态

添加状态

lv_obj_add_state(swtich1, 需要添加的状态);

删除状态

lv_obj_clear_state(swtich1, 需要删除的状态);

状态可以 ‘‘与’’ 上 LV_STATE_DISABLE 变成状态不可修改。

3.5.4 判断开关状态

是否处于某个值,返回bool类型,开为1,关为0

lv_obj_has_state(部件名,状态);

3.6 lv_chechbox 复选框部件

组成部分:

  • 主体 LV_PART_MAIN
  • 勾选框 LV_PART_INDICATOR
3.6.1 创建复选框部件
lv_obj_t* checkbox = lv_checkbox_create(parent);
3.6.2 文本设置

设置文本内容

lv_checkbox_set_text(部件名, "文本");

设置文本和勾选框的间距

lv_obj_set_style_pad_column(部件名, 间距, 选择器);

3.7 lv_img 图片部件

3.7.1 lv_img 图片部件使用

组成部分:

  • 主体 LV_PART_MAIN
3.7.1.1 创建图片部件
lv_obj_t* img = lv_img_create(parent);
3.7.1.2 设置图片源

图片源有两种方式:

  1. 将图片变成.c文件,用.c文件显示图片。
  2. 图片使用二进制文件展示

官方有转换工具 https://lvgl.io/tools/imageconverter,需要注意LVGL的版本对应!

LV_IMG_DECLARE(img_bird);	 // 声明图片
lv_img_set_src(img. &img_bird);	 // 设置图片源
3.7.1.3 设置图片偏移

图片偏移多余的部分会跑回开头。例如下面这段文字是你的图片信息 “我是图片123”,设置x轴偏移2,就会变成 “23我是图片1”,"23"就到前面去了。Y轴同理

lv_img_set_offset_x(img, 偏移量);  // x轴偏移
lv_img_set_offset_y(img, 偏移量);  // y轴偏移
3.7.1.4 图片重新着色

有种加滤镜的效果

lv_obj_set_style_img_recolor(img, lv_color_hex(Oxffe1d2), LV_PART_MAIN);
lv_obj_set_style_img_recolor_opa(img, 150, LV_PART_MAIN);

记住设置透明度,不然无法正常显示着色

3.7.1.5 设置图片缩放、旋转
lv_img_set_zoom(img, 512);
lv_img_set_angle(img, 900);

在这里插入图片描述

3.7.1.6 设置中心点

默认中心点在图片的正中间,图片缩放旋转都是根据这个中心点进行的。

lv_obj_update_layout(img); // 更新图片布局信息
lv_img_set_pivot(img, 0, 0); // 设置中心点
3.7.2 图片的设置
3.7.2.1 显示图片需要开启LVGL对标准IO的支持

lv_conf.h文件中:

在这里插入图片描述

  • LV_USE_FS_STDIO

    • 是否启用C标准库文件系统驱动
    • 1启用
    • 0不启用
  • LV_FS_STDIO_LETTER 配置盘符

    • 'F' → FatFS (SD 卡)
    • 'S' → StdIO (标准文件系统)
    • 'U' → UserFS (用户自定义)
  • LV_FS_STDIO_PATH

    • 设置文件操作的“根路径”。

    • LVGL 在拼接文件路径时,会自动把用户路径加到这个前缀后面。

    • 举例:

      #define LV_FS_STDIO_PATH "D:/lvgl_assets"
      

      如果你在 LVGL 里写:

      lv_img_set_src(img, "A:/images/pic.png");
      

      实际 fopen 的路径会变成:

      D:/lvgl_assets/images/pic.png
      
  • LV_FS_STDIO_CACHE_SIZE

    • lv_fs_read() 设置缓存大小(字节数)。
    • 0 → 不启用缓存,每次读直接调用 fread()
    • >0 → 分配一块缓存,用于提升连续小块读取的性能。

可以按照这个快速设置

在这里插入图片描述

3.7.2.2 开启图片格式接口

将需要的图片接口宏置1

在这里插入图片描述

3.7.2.3 调大malloc的空间

这里按需设置LV_MEM_SIZE大小,主要是防止图片过大内存会溢出。

在这里插入图片描述

3.8 lv_gif 动图部件

3.8.1 创建动图部件
lv_obj_t * gif1 = lv_gif_create(parent);
3.8.2 设置样式

设置gif路径

lv_gif_set_src(部件名, "gif图路径");

重新播放gif动画

lv_gif_restart(部件名);

四、部件的基本属性

4.1 大小 size

设置宽度

lv_obj_set_width(obj, new_width);

设置高度

lv_obj_set_height(obj, new_height);

同时设置宽度、高度

lv_obj_set_size(obj, new_width, new_height);

4.2 位置 position

在这里插入图片描述

  • 设置部件位置时,坐标原点在父对象的左上角

设置X轴坐标

lv_obj_set_x(obj, new_x, new_y);

设置Y轴坐标

lv_obj_set_y(obj, new_y);

同时设置X、Y轴坐标

lv_obj_set_pos(obj, new_x, new_y);

4.3 对齐alignment

参照父对象对齐

lv_obj_set_align(obj, LV_ALIGN_...);

参照父对象对齐,在进行偏移

lv_obj_align(obj, LV_ALIGN_.., x, y);

参照其他对象对齐(无父子关系),再进行偏移

lv_obj_align_to(obj_to_align, obj_referece, LV_ALIGN_..., x, y);
  • obj_to_align 需要对齐的对象
  • obj_referece 基准对象
4.3.1 对齐模式

在这里插入图片描述

分为内部与外部。内部与外部是基于类来规定的。

4.4 样式 styles

4.4.1 添加样式
  • 添加普通样式:
static lv_style_t style; 	
lv_style_init(&style);		
lv_style_set_bg_color(&style, lv_color_hex(0xf4b183));

样式使用:

lv_obj_t* obj = lv_obj_create(lv_scr_act()); 
lv_obj_add_style(obj, &style, LV_STATE_DEFAULT);
  • 添加本地样式:
lv_obj_t* obj = lv_obj_create(lv_scr_act());
lv_obj_set_style_bg_color(obj, lv_color_hex(0xf4b183), LV_STATE_DEFAULT); 
4.4.2 样式的部位

在这里插入图片描述

4.4.3 样式的属性

在这里插入图片描述

  • 轮廓在边框的外面
  • opa 透明度 越小越透明
4.4.4 设置部件中某个部分的样式

在这里插入图片描述

lv_obj_t* obj = lv_obj_create(lv_scr_act());
lv_obj_set_style_bg_color(obj, lv_color_hex(0xf4b183),
                          LV_STATE_DEFAULT | LV_PART_INDICATOR);
4.5 盒子模型

盒子是有默认的样式的,要想取消默认样式可以通过相关函数设置。

在这里插入图片描述


五、events 事件

监听某个部件发生某种情况执行某种结果。

5.1 事件的创建

lv_obj_add_event_cb(obj 部件名, event_cb 回调事件, filter 事件, user_date 参数);

static void my_event(lv_event_t *e)
{
  printf("LV_EVENT_CLICKED\n");
}

void mylv_event_cb()
{
  lv_obj_t *obj1 = lv_obj_create(lv_scr_act());
  lv_obj_add_event_cb(obj1, my_event, LV_EVENT_CLICKED, NULL);
}

回调函数的结构体 lv_event_t *e

typedef struct _lv_event_t {
    struct _lv_obj_t * target;
    struct _lv_obj_t * current_target;
    lv_event_code_t code;
    void * user_data;
    void * param;
    struct _lv_event_t * prev;
    uint8_t deleted : 1;
    uint8_t stop_processing : 1;
    uint8_t stop_bubbling : 1;
} lv_event_t;

5.2 事件动作

按下/释放相关

动作 事件类型 描述
按下 LV_EVENT_PRESSED 手指/鼠标按下对象时触发
松开 LV_EVENT_RELEASED 手指/鼠标释放对象时触发
点击 LV_EVENT_CLICKED 按下再松开且位置在对象范围内触发
双击 LV_EVENT_SHORT_CLICKED / LV_EVENT_LONG_PRESSED_REPEAT 短按重复触发或长按

移动/滑动相关

动作 事件类型 描述
拖动开始 LV_EVENT_DRAG_BEGIN 开始拖动对象时触发
拖动中 LV_EVENT_PRESSING 按住对象并移动时持续触发
拖动结束 LV_EVENT_DRAG_END 松开对象或拖动结束时触发
惯性拖动开始 LV_EVENT_DRAG_THROW_BEGIN 拖动惯性开始时触发
动作 事件类型 描述
获得焦点 LV_EVENT_FOCUSED 对象被选中/高亮时触发
失去焦点 LV_EVENT_DEFOCUSED 对象失去焦点时触发
值改变 LV_EVENT_VALUE_CHANGED 用于开关、滑块、复选框等值改变时触发

状态/焦点相关

动作 事件类型 描述
长按 LV_EVENT_LONG_PRESSED 按下超过一定时间触发
长按重复 LV_EVENT_LONG_PRESSED_REPEAT 长按期间每隔一定时间重复触发

5.3 关于回调函数获取部件信息有关函数

5.3.1 lv_event_get_code(e)
  • 获取当前事件的类型,例如 LV_EVENT_CLICKEDLV_EVENT_VALUE_CHANGED

  • 典型用法:

    if (lv_event_get_code(e) == LV_EVENT_CLICKED) {
        printf("Object clicked!\n");
    }
    
5.3.2 lv_event_get_target(e)
  • 获取触发事件的目标对象 lv_obj_t*

  • 相当于告诉你是谁触发了这个事件。

  • 典型用法:

    lv_obj_t *obj = lv_event_get_target(e);
    lv_obj_set_style_bg_color(obj, lv_color_hex(0xFF0000), 0); // 点击变红
    
5.3.3 lv_event_get_current_target(e)
  • 获取当前执行回调的对象(可能和 target 不同,用在冒泡/捕获事件时)。
5.3.4 lv_event_get_user_data(e)
  • 获取你在 lv_obj_add_event_cb 注册时传进去的 user_data
  • 可以用来传递额外参数,比如结构体指针。
5.3.5 其他函数:
  • lv_event_get_indev(e):获取触发事件的输入设备(如触摸屏)。
  • lv_event_stop_bubbling(e):阻止事件冒泡。
  • lv_event_stop_processing(e):阻止后续回调执行。

六、颜色

6.1 RGB 三原色

从红色、绿色和蓝色通道值创建颜色

//All channels are 0-255
lv_color_t c = lv_color_make(red, green, blue);

//From hex code 0x000000..0xFFFFFF interpreted as RED + GREEN + BLUE
lv_color_t c = lv_color_hex(0x123456); 

//From 3 digits. Same as lv_color_hex(0x112233)
lv_color_t c = lv_color_hex3(0x123); 

6.2 HSV 色调饱和值

根据色相、饱和度和值创建颜色

//h = 0..359, s = 0..100, v = 0..100
lv_color_t c = lv_color_hsv_to_rgb(h, s, v);

//All channels are 0-255
lv_color_hsv_t c_hsv = lv_color_rgb_to_hsv(r, g, b);


//From lv_color_t variable
lv_color_hsv_t c_hsv = lv_color_to_hsv(color);

6.3 调色板(内置颜色)

lvgl是有提供很多内置颜色(palette)的,如下:

  • LV_PALETTE_RED
  • LV_PALETTE_PINK
  • LV_PALETTE_PURPLE
  • LV_PALETTE_DEEP_PURPLE
  • LV_PALETTE_INDIGO
  • LV_PALETTE_BLUE
  • LV_PALETTE_LIGHT_BLUE
  • LV_PALETTE_CYAN
  • LV_PALETTE_TEAL
  • LV_PALETTE_GREEN
  • LV_PALETTE_LIGHT_GREEN
  • LV_PALETTE_LIME
  • LV_PALETTE_YELLOW
  • LV_PALETTE_AMBER
  • LV_PALETTE_ORANGE
  • LV_PALETTE_DEEP_ORANGE
  • LV_PALETTE_BROWN
  • LV_PALETTE_BLUE_GREY
  • LV_PALETTE_GREY

可以使用下面函数使用它们:

  1. lv_palette_main(palette)
  • 获取调色板的 主色 (main color)

  • 例如:

    lv_color_t c = lv_palette_main(LV_PALETTE_RED);
    lv_obj_set_style_bg_color(obj, c, 0);
    
  1. lv_palette_lighten(palette, lvl)
  • 获取调色板的 更亮的颜色

  • lvl 范围通常是 1~3(越大越亮)。

  • 例如:

    lv_color_t c = lv_palette_lighten(LV_PALETTE_BLUE, 2);
    lv_obj_set_style_bg_color(obj, c, 0);
    
  1. lv_palette_darken(palette, lvl)
  • 获取调色板的 更暗的颜色

  • lvl 范围通常是 1~4(越大越暗)。

  • 例如:

    lv_color_t c = lv_palette_darken(LV_PALETTE_GREEN, 3);
    lv_obj_set_style_bg_color(obj, c, 0);
    
使用场景 推荐格式
小图标 / 图形控件,有限色 CF_INDEXED_1/2/4/8_BIT
透明图标 / UI 界面元素 CF_TRUE_COLOR_ALPHACF_RGB565A8
背景图 / 全彩照片 CF_TRUE_COLORCF_TRUE_COLOR_CHROMA
纯色遮罩 / 字体 CF_ALPHA_1/2/4/8_BIT

通过这个链接查看调色板的具体颜色 VUETIFY:https://vuetifyjs.com/en/styles/colors/#material-colors


七、中文字库

  1. 选择字体文件(ttf, otf 等格式)
  2. 将字体文件转换成LVGL需要的字体库。(官方字体库在线转换工具链接: https://lvgl.io/tools/fontconverter)
  3. 选择字体转换的范围,范围越大字体涵盖就越多,相应的占用内存更多。(官方字体范围链接: https://lvgl.100ask.net/8.2/tools/fonts-zh-source.html)

在这里插入图片描述

注意:字体名称在创建的时候请注意C语言的命名规范,避免出现 - (短横杠) 这类的。

  1. 声明字体
LV_FONT_DECLARE(字体名)
  1. 调用字体
lv_obj_t* font_label = lv_label_create(lv_scr_act());  // 创建label标签
lv_obj_set_style_text_font(font_label, &声明的字体名, LV_STATE_DEFAULT); // 为label调用字体
lv_label_set_text(font_label, "文本内容"); // 设置文本内容

7.2 可能遇到的bug

7.2.1 static_bitmap = 0 不认识

把这段话注释就好,我的是v8.2版本的。

在这里插入图片描述

7.2.2 中文字库过大,需要开启大字库支持

在文件 lv_conf.h

#define LV_FONT_FMT_TXT_LARGE 1    // 置1

对于出现旧的错误,建议清除已有的缓解(make clean 清除之前编译的文件)重新编译。


十、定时器

10.1 定时器是什么

在 LVGL 里,定时器(lv_timer_t)就是一个 周期性执行的任务。它和你在 RTOS 或裸机里写的硬件定时器不一样,它依赖于 lv_timer_handler() 的运行,所以要保证主循环里定时调用 lv_timer_handler()

10.2 创建定时器

lv_timer_t * lv_timer_create(lv_timer_cb_t timer_xcb,
                             uint32_t period,
                             void * user_data);
  • timer_xcb:回调函数
  • period:间隔时间,单位毫秒
  • user_data:用户数据(传参)

示例

static void my_timer_cb(lv_timer_t * timer)
{
    int * count = timer->user_data;
    (*count)++;
    printf("tick %d\n", *count);
}

void init_timer(void)
{
    static int cnt = 0;
    lv_timer_t * timer = lv_timer_create(my_timer_cb, 1000, &cnt);
}

10.3 常用操作

  1. 删除定时器
lv_timer_del(timer);
  1. 重置定时器(下次执行重新开始计时)
lv_timer_reset(timer);
  1. 修改周期
lv_timer_set_period(timer, 500);  // 改成 500ms
  1. 设置执行次数
lv_timer_set_repeat_count(timer, 10); // 执行10次后自动删除
  1. 暂停 / 恢复
lv_timer_pause(timer);   // 暂停
lv_timer_resume(timer);  // 恢复

以上就是我对LVGL学习笔记,笔记中还有很多LVGL的部件和知识点未提及,可以通过LVGL官方文档进行查阅,也可以通过百问网查询资料学习(百问网链接:https://lvgl.100ask.net/8.2/index.html)。

Logo

更多推荐