lvgl入门学习第三篇lvgl部件
一、标签(lv_label)
标签是用来显示文本的基本对象类型。
在盒子模型里面,标签的组成包括:
- LV_PART_MAIN 矩形部分(盒子区域)。 填充值可用于在文本和背景之间添加空间。
- LV_PART_SCROLLBAR 当要展示的文本大于部件的大小时,显示的滚动条部分。
- LV_PART_SELECTED 选中文本时,突出显示的部分。label只能使用 text_color 和 bg_color 样式属性。
创建标签:lv_obj_t * label = lv_label_create(parent);
1.1 设置显示文本
创建了标签部件之后我们就可以设置文本来显示。
- 直接设置要显示的文本:
lv_label_set_text(label, "New text");
- 格式化给定要显示的文本:
lv_label_set_text_fmt(label, “%s: %d”, “Value”, 15);
- 文本不存储在动态内存中,而是直接使用给定的缓冲区:
lv_label_set_text_static(label, "New text");
- 在label换行,像printf函数那样使用 \n 即可:
lv_label_set_text(label, " line1\nline2\n\nline4 ");
1.2 大小
- 默认情况标签的大小会自动拓展成和文本一样的大小(LV_SIZE_CONTENT),也可以设置宽高:
lv_obj_set_size lv_obj_set_width lv_obj_set_height
- 这样就可能出现文本的宽度或高度大小与label不一样的情况,需要做一些调整,下面是几种模式:
LV_LABEL_LONG_WRAP 如果有多个换行,并且如果高度为LV_SIZE_CONTENT,那么高度会根据文本换行被自动扩展;否则文本将被剪掉。(默认设置)
LV_LABEL_LONG_DOT 如果文本太长,就保持大小并在末尾写3个点。
LV_LABEL_LONG_SCROLL 如果文本比标签宽(太长),则可以水平来回滚动显示它。如果它很高(多个\n换行),可以垂直滚动。只滚动一个方向,水平滚动的优先级更高。LV_LABEL_LONG_SCROLL_CIRCULAR 如果文本比标签宽,则水平滚动它。如果它更高,就垂直滚动。只滚动一个方向,水平滚动的优先级更高。
LV_LABEL_LONG_CLIP 剪掉超出标签范围外的文本部分。
可以使用 lv_label_set_long_mode(label, LV_LABEL_LONG_...) 指定模式。
- 注意:
1、LV_LABEL_LONG_DOT 是直接操作文本缓冲区以添加/删除点。
2、使用 lv_label_set_text 和 lv_label_set_text_fmt 会分配一个单独的缓冲区,不会出问题。
3、使用 lv_label_set_text_static 时我们传递给它的缓冲区必须是可写的。
1.3 文本着色
对要显示的文本重新着色,可以通过样式来上色,例如:lv_style_set_text_color(&style_obj, lv_color_hex(0xf7b37b));
lv_obj_set_style_text_color(label, lv_color_hex(0xf7b37b), 0);
也可以让文本某些部分重新着色,例如:
lv_label_set_recolor(label1, true);
lv_label_set_text(label1, "#0000ff Re-color# #ff00ff words# #ff0000 of a# label);
1.4 文本选择
-
如果在 lv_conf.h 中打开了 LV_LABEL_TEXT_SELECTION (默认开启),就可以选择部分文本。这个和我们在PC用鼠标选中文本类似。但是这个效果只能在文本框(lv_textarea)中实现。Label只能事先手动选择指定范围的文本:
lv_label_set_text_sel_start(label, 1);
lv_label_set_text_sel_end(label, 6);
-
注意,这里的第一个字符从1开始算,而不是0。
1.5 显示图标
LVGL内置了一些图标,它们是全局变量,可以直接使用:
用法(LV_SYMBOL_...):
lv_label_set_text(my_label, LV_SYMBOL_OK); // 直接显示图标
lv_label_set_text(my_label, LV_SYMBOL_OK “Apply”); // 图标与字符串一起使用
lv_label_set_text(my_label, LV_SYMBOL_OK LV_SYMBOL_WIFI LV_SYMBOL_PLAY); // 多个图标一起使用
1.6 事件处理
Label默认不接收输入事件,如果想设置输入类型的样式或者事件会无法生效,需要打开 LV_OBJ_FLAG_CLICKABLE, 示例:lv_obj_add_flag(label, LV_OBJ_FLAG_CLICKABLE); // 使输入设备可点击对象
1.7 显示中文
- LVGL内置有一个中文字库 CJK字库 ,这个字库在 lv_conf.h中定义为:
LV_FONT_SIMSUN_16_CJK
。 - 要在lvgl中使用显示自己的中文字库,需要用到两个东西:字体文件和字体转换器。
- 字体文件使用开源的字体或者自己制作出来,准备好了字体文件之后使用字体转换器即可转换成可以在lvgl上使用的字体格式。开源字体获取页面:http://lvgl.100ask.net/8.1/tools/fonts-zh-source.html
- 准备好字体文件之后就可以通过lvgl官方提供的字体转换器,提取转换你想要的字体,LVGL官方在线字体转换器页面:https://lvgl.io/tools/fontconverter
1.8 如何使用字体转换器?
- 为要输出字体命名。例如“font_source_han_sans_bold_20”
- 以 px为单位指定高度(字体大小)
- 设置bpp (bit-per-piel)。值越高,字体越平滑(抗锯齿)
- 选择TTF 或 WOFF 格式字体文件
- 设置要包含在字体中的Unicode 字符范围或在符号字段中列出字符
- 可以同时选择多个字体文件转换,并为其指定范围和/或符号。这些字符将被合并转换到同一个文件中。
- 单击转换按钮以下载转换出来的 font_source_han_sans_bold_20.c 文件。
1.9 如何在 LVGL 中使用生成的字体?
- 将结果 C 文件复制到LVGL 项目中,并包含到项目;
- 在项目应用程序的 C 文件中,将字体声明为:
extern lv_font_t my_font_name; 或:LV_FONT_DECLARE(my_font_name);
- 在样式中设置字体:
lv_style_set_text_font(&style_obj, &my_font_name); // 普通(共享)样式
lv_obj_set_style_text_font(label, &my_font_name, 0); // 私有(本地)样式
- unicode 是统一所有语言的一套编码。
- utf-8是基于unicode编码的一种节约字节的编码。
二、按钮(lv_btn)
- 按钮是和基础对象最像的部件。与基础对象相比,按钮没有新的功能,只是默认的样式和基础对象不一样。
- 默认情况,按钮和基础对象的不同点:
不可滚动
添加到默认组(可修改为给其他输入设备控制用,比如按键)
高度和宽度默认为 LV_SIZE_CONTENT - 创建按键的方法:
lv_obj_t * btn = lv_btn_create(parent);
为什么按钮和基础对象的默认样式不一样?
他们的创建接口都是一样的,是在什么时候、哪里决定了他们不一样的样式呢?
这要从lvgl默认的主题样式说起。
默认主题的初始化和应用过程:
lv_disp_drv_register
lv_theme_default_init
style_init
theme.apply_cb = theme_apply;
-----------------------------------------------
lv_xxx_create
lv_obj_class_init_obj
lv_theme_apply
apply_theme(th, obj);
2.1 部分和样式
- 按钮的组成部分和基础对象一样,只有一个空空的盒子(盒子模型)。
- 按钮的部分(Part)只有下面这个:
LV_PART_MAIN 按钮的背景
- 样式修改示例:
lv_obj_set_style_<property_name>(obj, <value>, <selector>);// 本地(私有)样式
lv_obj_add_style(obj, &style, <selector>) // 普通(共享)样式
所以修改样式的时候我们修改部分(Part)的时候只有 LV_PART_MAIN 可以生效;状态部分和前面说的样式状态(States)都可以用
2.2 事件
事件可以像前面说的事件处理部分使用,但注意如下:
打开 LV_OBJ_FLAG_CHECKABLE ,当对象被点击时有选中切换(Toggle)状态的效果,并且可以在 LV_EVENT_VALUE_CHANGED 事件类型中处理事件,比如:lv_obj_add_flag(btn, LV_OBJ_FLAG_CHECKABLE);
2.3 按键控制
总的来看,按钮是用来按的(单击、按下或不按下),所以我们用物理按键控制的时候只需要 LV_KEY_ENTER 就可以控制按钮,
并且LV_KEY_ENTER 可以触发 LV_EVENT_PRESSED/PRESSING/RELEASED 等事件类型
三、使用物理按键代替触摸(groups)
3.1 组(groups)
- 在LVGL中我们可以使用键盘或编码器替换触摸板或鼠标控制。它的工作原理类似于 PC 上的 TAB 键,用于选择应用程序或网页中的元素。
- 首先将要用键盘或编码器控制的部件添加到组,有的部件在创建时会加入到默认组。
- 在每个组中,同时只有一个对象聚焦并接收按键或编码器动作。
- 将输入设备与组关联。一个输入设备只能将按键发送给一组,反过来一组可以从多个输入设备接收数据。
- 5种输入设备类型:
LV_INDEV_TYPE_NONE 不使用输入设备(未初始化状态)
LV_INDEV_TYPE_POINTER 触摸板、鼠标、外接按钮
LV_INDEV_TYPE_KEYPAD 键盘
LV_INDEV_TYPE_BUTTON 分配给屏幕特定点的外部(硬件按钮)
LV_INDEV_TYPE_ENCODER 只有左、右和按下三个按键的编码器(比如鼠标中间的滚轮)
3.2 自定义组创建过程
- 首先创建一个 组(Groups) :
lv_group_t * g = lv_group_create()
; - 然后将一个对象添加到 组(Groups) 中:
lv_group_add_obj(g, obj)
; - 最后要将组(Groups)与输入设备相关联:
lv_indev_set_group(indev, g)
;其中 indev 是 lv_indev_drv_register(); 的返回值
3.3 使用默认组
在lvgl中有些部件,在创建的时候加入到默认组中,但是默认组变量lvgl并没有帮我们初始化,需要在创建部件之前初始化才能使用默认组,对于创建时添加到默认的部件我们可以跳过lv_group_add_obj:
lv_group_t * g = lv_group_create(); // 创建一个组
lv_group_set_default(g); // 设置为默认组
lv_indev_set_group(indev, g); // 将组和输入设备相关联
3.4 预定义按键
有一些预定义的键具有特殊含义:
3.5 必须的按键
-
最重要且建议必要的按键是:
- LV_KEY_NEXT/PREV
- LV_KEY_ENTER
- LV_KEY_UP/DOWN/LEFT/RIGHT
-
在回调函数 read_cb 中,应该优先考虑将现有的键对应转换为上面这些键,以便能在组中导航并与所选对象进行交互。
-
一般来说,只使用 LV_KEY_LEFT/RIGHT 就足够,因为大多数对象都可以通过它们被完全控制。
-
对于编码器,默认只使用 LV_KEY_LEFT、LV_KEY_RIGHT 和 LV_KEY_ENTER
3.6 编辑(edit)和导航(navigate)模式
- 编码器的按键有限,所以在各个对象之间进行导航就不方便了,lvgl分两种模式:编辑和导航模式
- 导航模式下,编码器的 LV_KEY_LEFT/RIGHT 被转换为 LV_KEY_NEXT/PREV,可以通过转动编码器来选择下一个或上一个对象。
- 如果需要修改对象的值,比如有个滑杆(lv_slider)代表音量或亮度,通过按下LV_KEY_ENTER 将模式切换为编辑模式,这样我们可以通过转动编码器来修改滑杆的值。然后根据对象的类型,短按或长按 LV_KEY_ENTER 切换为导航模式(离开编辑模式)。
3.7 默认组(Default group)
- 交互式小部件 - 例如按钮、复选框、滑块等,在创建时会自动添加到默认组。默认组是:
- 我们可以修改默认组为自己定义的:
lv_group_t * g = lv_group_create(); // 创建组
lv_group_set_default(g); // 设置默认组
lv_indev_set_group(my_indev, g); //将输入设备分配到默认组。
3.8 风格样式
- 通过触摸板点击选中对象或通过编码器或键盘聚焦对象,对象的状态会变为 LV_STATE_FOCUSED。
- 如果对象进入编辑模式,对象将进入 LV_STATE_FOCUSED | LV_STATE_EDITED 状态。
- 所以,可以根据上面两点,为对象设置被选中或聚焦或编辑时的样式。
3.9 按键控制的初始化、工作流程和使用
lv_init
_lv_group_init
lv_indev_drv_register
lv_timer_create(lv_indev_read_timer_cb, LV_INDEV_DEF_READ_PERIOD, indev);
lv_indev_read_timer_cb
_lv_indev_read(indev_act, &data); // 读取按键数据
indev->driver->read_cb(indev->driver, data);
indev_keypad_proc
lv_group_send_data(g, LV_KEY_...);
lv_event_send(act, LV_EVENT_KEY, &c); // 发送处理按键事件,传递的参数是具体哪个按键
lv_event_send(indev_obj_act, LV_EVENT_..., indev_act); // 模拟对对象的操作,比如按下事件
-----------------------------------------------
lv_xxx_create
lv_obj_class_init_obj
lv_group_add_obj
3.10 基础对象的作用
- 基础对象是所有部件(对象)的基石,基础对象将所有对象的共性抽象出来。
- 使用物理按键或触摸的时候,为什么对象知道自己被聚焦(选中)并且做出回应的呢?
其实这些基础对象都已经做好了,后面创建的对象直接使用即可。
四、开关(lv_switch)
- 开关的功能类似于按钮,也可以用来打开和关闭某些东西。
- 创建开关的方法:
lv_obj_t * sw = lv_switch_create(parent)
;
4.1 零件和样式
开关包括以下3个零件:
- LV_PART_MAIN 背景。 修改其 padding 会让下面的(指示器)在相应方向上的大小发生变化。
- LV_PART_INDICATOR 显示开关状态的指示器。
- LV_PART_KNOB 在指标左侧或右侧的旋钮。 默认情况下,旋钮是圆形的,边长等于滑块的较小边。 可以修改 padding 值使旋钮变大,填充值可以是不对称的。
示例:
// 修改开关背景部分的颜色
lv_obj_set_style_bg_color(sw, lv_color_hex(0xc43e1c), LV_PART_MAIN);
// 修改 pad,改变指示器在相应方向上的大小
lv_obj_set_style_pad_left(sw, 5, LV_PART_MAIN); // lv_obj_set_style_pad...
// 修改开关状态指示器部分,关闭状态时的背景颜色
lv_obj_set_style_bg_opa(sw, 100, LV_PART_INDICATOR);
lv_obj_set_style_bg_color(sw, lv_color_hex(0xc43e1c), LV_PART_INDICATOR);
// 修改开关状态指示器部分,打开状态时的背景颜色
lv_obj_set_style_bg_color(sw, lv_color_hex(0x7719aa), LV_PART_INDICATOR | LV_STATE_CHECKED);
// 修改开关旋钮部分的颜色
lv_obj_set_style_bg_color(sw, lv_color_hex(0xc43e1c), LV_PART_KNOB);
4.2 用法
- 当开关被打开时,开关的状态会变为 LV_STATE_CHECKED 。我们可以通过下面这两个接口获取开关当前的状态:
lv_obj_has_state(switch, LV_STATE_CHECKED); // 返回 bool 类型, 开-1 ; 关-2
lv_obj_get_state(switch); // 返回枚举类型: LV_STATE_...
- 一般我们通过触摸或按键控制让开关 打开/关闭,还可以通过下面这个接口来主动 打开/关闭:
lv_obj_add_state(switch, LV_STATE_CHECKED); // 开
lv_obj_clear_state(switch, LV_STATE_CHECKED); // 关
- 可以通过下面的接口让按钮处于不可更改状态:
lv_obj_add_state(sw, LV_STATE_DISABLED); // 当前状态是关,并且不可更改
lv_obj_add_state(sw, LV_STATE_CHECKED | LV_STATE_DISABLED); // 当前状态是开,并且不可更改
- 让按钮恢复可以更改的状态,只要将 LV_STATE_DISABLED 清除即可:
lv_obj_clear_state(switch, LV_STATE_ DISABLED); // 清除禁用状态,按钮可正常使用
4.3 事件处理
正常情况下,当开关被点击并且状态发生改变时,触发 LV_EVENT_VALUE_CHANGED 事件类型。也就是说可以在 LV_EVENT_VALUE_CHANGED 事件类型中处理事件,比如: lv_obj_add_event_cb(switch, event_handler, LV_EVENT_VALUE_CHANGED, NULL);
4.4 按键控制
LV_KEY_UP/RIGHT 开
LV_KEY_DOWN/LEFT 关
LV_KEY_ENTER 切换开关
本文来自博客园,作者:登云上人间,转载请注明原文链接:https://www.cnblogs.com/lj15941314/p/17207869.html