工具篇
生成 lvgl 字体
使用 LvglFontTool 工具(最新 v0.4)生成 lvgl 上的字体 c 文件;
开始:
-
选择字体
我选择“宋体” –> “常规” –> “12”
-
加入常用汉字,并清除重复
-
插入 awesome 字体图标,选择添加所有图标
添加完后点确定即可
-
输入字体名称,点击开始转换
我这里输入的是 lv_font_songti12
-
转换完成后点击保存,得到
lv_font_songti12.c
使用 LvglFont
-
将上一步得到的
lv_font_songti12.c
文件放在lvgl/src/lv_font/
目录下; -
在应用源文件上方外部声明 lv_font_songti_12 字体资源;
1
LV_FONT_DECLARE(lv_font_songti_12);
-
新建一个样式 style1,使用 lv_font_songti_12 字体
1 2 3
static lv_style_t style1; lv_style_reset(&style1); lv_style_set_text_font(&style1, LV_STATE_DEFAULT, &lv_font_songti_12);
-
新建一个 label,使用 style1 样式
源文件应使用 utf8 编码,
\uF004
是 awesome 中的爱心图标♥显示效果:[左上角] “中文 english ♥”
1 2 3 4
lv_obj_t *label = lv_label_create(lv_scr_act(), NULL); lv_obj_add_style(label, LV_OBJ_PART_MAIN, &style1); lv_label_set_text(label, "中文 english \uF004"); lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);
生成 lvgl 单色图片
工具1:
工具2:
Image2Lcd v3.2(右下角注册:0000-0000-0000-0000-6A3B)
开始:
-
使用 Image2Lcd 打开一张图片进行处理;
-
处理为单色,输出为
img_test.bmp
;得到的图片可用 “Windows 画图” 继续编辑修改;
-
打开 lvgl 在线图片转换,选择上一步的 bmp 文件;
-
输入名称 img_test,Color format 选择 “Indexed 2 colors”;
-
点击转换后生成
img_test.c
;
使用 lvgl 图片
-
将
img_test.c
加入到工程; -
在应用源文件上方外部声明 img_test 图片资源;
1
LV_IMG_DECLARE(img_test);
-
新建一个图像 img1 使用 img_test 资源;
1 2 3
lv_obj_t *img1 = lv_img_create(lv_scr_act(), NULL); lv_img_set_src(img1, &img_test); lv_obj_align(img1, NULL, LV_ALIGN_CENTER, 0, 0);
基础篇
基础
信息
任务处理都在(动态的都在这里执行):
lv_task_handler();
系统时间相关(告诉 lvgl 时间过了多久),每隔 x 毫秒调用一次:
lv_tick_inc(x);
角度
lvgl 的角度范围是:0~360 度;
其中,正右方是 0 度,顺时针转,正下方是 90 度;
日志
启用功能:
1
2
#define LV_USE_LOG 1
#define LV_LOG_LEVEL LV_LOG_LEVEL_INFO
具体实现:
能使用 printf 的开启下面的宏:
1
#define LV_LOG_PRINTF 1
不能使用 printf 的参考官方教程——日志;
对象
下面只涉及基本属性;
大小和位置
1
2
3
4
5
6
7
8
# 大小固定
lv_obj_set_size(btn1, 100, 50);
# 大小适应内容
lv_btn_set_fit(btn1, true, true);
# 绝对位置
lv_obj_set_pos(btn1, 20,30);
# 使用对齐
lv_obj_align(btn1, NULL, LV_ALIGN_CENTER, 0, 0);
点击和拖动使能
1
2
lv_obj_set_click(btn1, true);
lv_obj_set_drag(btn, true);
父级
子对象位置 (0, 0) 是相对父对象的位置;
超出父对象大小的部分将不可见;
1
2
3
4
5
6
7
8
9
10
//par 父级是当前屏幕
lv_obj_t * par = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_size(par, 100, 80);
//child 父级是 par
lv_obj_t * child = lv_obj_create(par, NULL);
lv_obj_set_pos(child, 10, 10);
//也可以给已有对象设置父级
lv_obj_set_parent(obj, new_parent)
屏幕
1
2
3
4
5
6
7
8
9
10
11
# 获取当前活动屏幕
lv_obj_t * scr_act = lv_scr_act();
# 创建新的屏幕
lv_obj_t * scr2 = lv_obj_create(NULL, NULL);
# 加载屏幕
lv_scr_load(scr2);
# 删除屏幕,不能删除当前加载的屏幕
lv_obj_del(scr3);
创建和删除对象
1
2
3
4
5
6
7
8
9
10
11
# 创建对象
lv_obj_t * lv_ <type>_create(lv_obj_t * parent, lv_obj_t * copy);
# 删除对象和所有子对象
void lv_obj_del(lv_obj_t * obj);
# 删除对象,不包括子对象
lv_obj_del_async(obj);
# 删除对象的所有子对象(不包括对象)
void lv_obj_clean(lv_obj_t * obj);
对象状态(状态可组合)
当用户按下、释放、焦点等对象时,库通常会自动更改状态。但是,也可以手动更改状态。
1
2
lv_obj_set_state(obj, part, LV_STATE...)
lv_obj_add/clear_state(obj, part, LV_STATE_...)
- LV_STATE_DEFAULT 正常,释放
- LV_STATE_CHECKED 切换或选中
- LV_STATE_FOCUSED 通过键盘或编码器聚焦或通过触摸板/鼠标单击
- LV_STATE_EDITED 编码器编辑
- LV_STATE_PRESSED 压
- LV_STATE_DISABLED 已禁用或非活动
图层
1
2
3
4
5
6
7
8
9
10
11
12
13
# 使能单击子级设置到顶层(除 sys 悬浮层的最上层'悬浮层放鼠标图标等')
lv_obj_set_top(obj, true);
# 上移到前景
lv_obj_move_foreground(obj);
# 下移
lv_obj_move_background(obj);
# 获取顶层对象
lv_obj_t * obj_top = lv_layer_top();
# 设置父级,会置于父级的上层
lv_obj_set_parent(obj, new_parent);
核心篇
事件
分配回调函数:
多个对象可以使用同一个回调函数;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
lv_obj_t * btn = lv_btn_create(lv_scr_act(), NULL);
lv_obj_set_event_cb(btn, my_event_cb);
...
static void my_event_cb(lv_obj_t * obj, lv_event_t event)
{
switch(event) {
case LV_EVENT_PRESSED:
printf("Pressed\n");
break;
case LV_EVENT_SHORT_CLICKED:
printf("Short clicked\n");
break;
case LV_EVENT_CLICKED:
printf("Clicked\n");
break;
case LV_EVENT_LONG_PRESSED:
printf("Long press\n");
break;
case LV_EVENT_LONG_PRESSED_REPEAT:
printf("Long press repeat\n");
break;
case LV_EVENT_RELEASED:
printf("Released\n");
break;
}
/*Etc.*/
}
所有的事件,看官方文档——事件类型;
- 与输入相关的事件
- 与指针拖动相关的事件
- 与特定对象相关的事件
- 库发送的事件——LV_EVENT_DELETE 正在删除对象
手动发送事件:
1
2
3
4
5
6
7
8
9
# 发送事件带数据
lv_event_send(mbox, LV_EVENT_VALUE_CHANGED, "xxx");
# 获取当前对象的 LV_EVENT_VALUE_CHANGED 事件附带的数据
# 只在回调函数中使用
lv_event_get_data();
# 发送事件仅刷新
lv_event_send(label, LV_EVENT_REFRESH, NULL);
样式
太多了,直接看官方文档——样式;
输入设备
枚举值有 LV_KEY_PREV、LV_KEY_NEXT、LV_KEY_ENTER 等;
直接看官方文档——输入设备;
动画
直接看官方文档——动画;
任务
创建任务
需要先设置回调函数 task_cb;
1
2
3
4
5
# 创建任务
lv_task_create(task_cb, period_ms, LV_TASK_PRIO_OFF/LOWEST/LOW/MID/HIGH/HIGHEST, user_data);
# 删除任务
lv_task_del(task_cb);
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void my_task(lv_task_t * task)
{
/*Use the user_data*/
uint32_t * user_data = task->user_data;
printf("my_task called with user data: %d\n", *user_data);
/*Do something with LVGL*/
if(something_happened) {
something_happened = false;
lv_btn_create(lv_scr_act(), NULL);
}
}
...
static uint32_t user_data = 10;
lv_task_t * task = lv_task_create(my_task, 500, LV_TASK_PRIO_MID, &user_data);
设置参数
修改已存在任务的参数;
lv_task_set_cb(task, new_cb)
lv_task_set_period(task, new_period)
lv_task_set_prio(task, new_priority)
任务控制
任务建立后,是由库定时调用的(lv_task_handler 函数);
一次性任务是,库首次调用任务后,将自动删除该任务;
不等待计时,立刻就绪:lv_task_ready(task)
一次性任务:lv_task_once(task)
重置任务:lv_task_reset(task)
异步调用
以下是示例,当前屏幕未使用后删掉它;
1
2
3
4
5
6
void my_screen_clean_up(void * scr)
{
lv_obj_del(scr);
}
lv_async_call(my_screen_clean_up, lv_scr_act());
组件篇
按钮
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
static lv_style_t style_btn;
//创建一个简单的按钮风格
lv_style_init(&style_btn);
//圆角:10
lv_style_set_radius(&style_btn, LV_STATE_DEFAULT, 10);
//透明度:不透明
lv_style_set_bg_opa(&style_btn, LV_STATE_DEFAULT, LV_OPA_COVER);
//背景:白色(起点)
lv_style_set_bg_color(&style_btn, LV_STATE_DEFAULT, LV_COLOR_WHITE);
//背景渐变:终点白色-以下不设置吧,下同
//lv_style_set_bg_grad_color(&style_btn, LV_STATE_DEFAULT, LV_COLOR_WHITE);
//渐变方向:从上到下
//lv_style_set_bg_grad_dir(&style_btn, LV_STATE_DEFAULT, LV_GRAD_DIR_VER);
//渐变起始点:0:在左/上最位置,255:在右/下最位置
//lv_style_set_bg_main_stop(&style, LV_STATE_DEFAULT, 0);
//渐变终止点:0:在左/上最位置,255:在右/下最位置
//lv_style_set_bg_grad_stop(&style, LV_STATE_DEFAULT, 0);
//设置边框
lv_style_set_border_color(&style_btn, LV_STATE_DEFAULT, LV_COLOR_BLACK);
lv_style_set_border_opa(&style_btn, LV_STATE_DEFAULT, LV_OPA_COVER);
lv_style_set_border_width(&style_btn, LV_STATE_DEFAULT, 2);
//设置文字风格
lv_style_set_text_color(&style_btn, LV_STATE_DEFAULT, LV_COLOR_BLACK);
lv_style_set_text_font(&style_btn, LV_STATE_DEFAULT, LV_THEME_DEFAULT_FONT_NORMAL);
//创建按钮使用上述风格
lv_obj_t * btn = lv_btn_create(lv_scr_act(), NULL); //添加按钮到当前屏幕
lv_obj_set_pos(btn, 10, 10); //设置位置
lv_obj_set_size(btn, 60, 30); //设置大小
lv_obj_reset_style_list(btn, LV_BTN_PART_MAIN); //从主题中删除风格
lv_obj_add_style(btn, LV_BTN_PART_MAIN, &style_btn); //添加自定义风格
lv_obj_t * label = lv_label_create(btn, NULL); //按钮上加入子标签
lv_label_set_text(label, "Button"); //设置标签文字
标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 长标签:超过宽度自动换行
lv_obj_t * label1 = lv_label_create(lv_scr_act(), NULL);
lv_label_set_long_mode(label1, LV_LABEL_LONG_BREAK);
lv_label_set_align(label1, LV_LABEL_ALIGN_CENTER);
lv_label_set_text(label1, "long long line of a label emmm... and emmmmmm...");
lv_obj_set_width(label1, 120);
lv_obj_align(label1, NULL, LV_ALIGN_CENTER, 0, -30);
# 长标签:使用滚动
lv_obj_t * label2 = lv_label_create(lv_scr_act(), NULL);
lv_label_set_long_mode(label2, LV_LABEL_LONG_SROLL_CIRC);
lv_obj_set_width(label2, 120);
lv_label_set_text(label2, "It is a circularly scrolling text.");
lv_obj_align(label2, NULL, LV_ALIGN_CENTER, 0, 30);
圆弧
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static lv_style_t style1;
lv_style_init(&style1);
lv_style_set_bg_color(&style1, LV_STATE_DEFAULT, LV_COLOR_WHITE);
lv_style_set_line_width(&style1, LV_STATE_DEFAULT, 0); //Hide the background arc transparent
static lv_style_t style2;
lv_style_init(&style2);
lv_style_set_line_color(&style2, LV_STATE_DEFAULT, LV_COLOR_BLACK);
lv_style_set_line_width(&style2, LV_STATE_DEFAULT, 3);
/*Create an Arc*/
lv_obj_t * arc = lv_arc_create(lv_scr_act(), NULL);
lv_obj_add_style(arc, LV_OBJ_PART_MAIN, &style1);
lv_obj_add_style(arc, LV_ARC_PART_INDIC, &style2);
lv_obj_set_size(arc, 120, 120);
lv_arc_set_bg_angles(arc, 0, 360);
lv_arc_set_angles(arc, 0, 270);
lv_obj_align(arc, NULL, LV_ALIGN_CENTER, 0, 0);
这里只是抛砖引玉,其他请参考 LVGL 官方文档;