LVGL作为EmWin的一个开源替代,在做国产替代项目经常用到,结合国产的MCU可以说是绝配。

这里汇总LVGL里面常用的一些设置和组件的使用。

一般用lv_imgbtn作为最常用的组件,结合坐标可以实现界面的完全自定义。

使用LVGL做大型的自定义界面,配置方面最好多带一块外置的Flash例如:

华邦(Winbond) 25Q128JVSIQ 128Mbit(16MB) 存储芯片 如果界面比16MB还要大,还可以用32MB的存储芯片

华邦(Winbond) W25Q256JVSIQ 256Mbit (32MB) 存储芯片

有了大的存储空间,自定义的UI就可以任意发挥了。

工具软件

  • Lvgl_image_convert_tool

离线的图片转换工具,可以转换图片为C文件或者是bin文件

  • LvglFontTool_V0.4 LVGL字库制作工具, 当要显示中文的时候,这个是必备工具, 把项目中要用到的文字制作成C文件嵌入到项目中来,就能显示中文。

常用的LVGL代码

调试日志输出

1
  LV_LOG_USER("Clicked date: %02d.%02d.%d", date.day, date.month, date.year); //打印日历信息

日志输出尽量不要用printf()函数,后期作为正式产品输出的时候不方便禁用

禁止屏幕滑动和出现滚动条

1
lv_obj_clear_flag(lv_scr_act(),LV_OBJ_FLAG_SCROLLABLE);

一般主屏幕设置成禁止滚动会比较好。

位置,文本,事件绑定

1
2
3
4
5
6
lv_obj_set_pos(btn1, 20, 20);//设置坐标
lv_obj_set_size(btn1, 150, 50);//设置大小
lv_obj_set_event_cb(btn1, btn_event_cb);//设置回调函数

lv_obj_t* label = lv_label_create(btn1, NULL);//给 btn1 添加 label 子对象
lv_label_set_text(label, "Click me");//设置文本

创建图片按钮

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
static lv_obj_t* create_menu_button(lv_obj_t *parent, const void *press_icon,
		const void *relese_icon, lv_coord_t x, lv_coord_t y) {
	lv_obj_t *icon = lv_imgbtn_create(parent);
	lv_imgbtn_set_src(icon, LV_IMGBTN_STATE_CHECKED_RELEASED, relese_icon, NULL,
	NULL);
	lv_imgbtn_set_src(icon, LV_IMGBTN_STATE_CHECKED_PRESSED, press_icon,
	NULL,
	NULL);
	lv_imgbtn_set_state(icon, LV_IMGBTN_STATE_CHECKED_RELEASED);
	lv_obj_set_pos(icon, x, y);
	lv_img_set_antialias(parent, false);
	return icon;
}

按钮点击事件处理函数

 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
36
/**
 * 手动点击接水事件
 * @param event
 */
void menu_start_event_cb(lv_event_t *event) {
	lv_event_code_t code = lv_event_get_code(event); //获取事件code
	if (code == LV_EVENT_PRESSED) {
		/* 对象被长按 */
		//按下 水机开始工作
		water_machine_start_work();
		//显示警告消息
		show_warn_msg(WARN_CODE_CUP_HOT);
	} else if (code == LV_EVENT_LONG_PRESSED) {
		/* 对象被长按 */
		//长按 水机开始工作
		water_machine_start_work();
		//显示警告消息
		show_warn_msg(WARN_CODE_CUP_HOT);
	} else if (code == LV_EVENT_LONG_PRESSED_REPEAT) {
		/* 对象被重复长按 */
		//长按 水机开始工作
		water_machine_start_work();
		//显示警告消息
		show_warn_msg(WARN_CODE_CUP_HOT);
	} else if (code == LV_EVENT_RELEASED) {
		/* 对象被释放 */
		//释放,停止出水
		water_machine_stop_work();
		//隐藏警告消息
		show_warn_msg(WARN_CODE_HIDDEN);

	}
	if (code == LV_EVENT_VALUE_CHANGED) { //值改变事件处理
		//lv_obj_t* obj = lv_event_get_current_target(e); //获取事件产生的对象
	}
}

调用

1
2
3
4
5
//定义对象
lv_obj_t *menu_start;
//创建按钮
menu_start = create_menu_button(lv_scr_act(), &menu_tea_p,
			&menu_tea_r, 621, 50);

使得图片按钮可以点击

1
lv_obj_add_flag(menu_start, LV_OBJ_FLAG_CLICKABLE);

禁止某个组件的点击功能

隐藏图片按钮

1
lv_imgbtn_set_state(menu_start, LV_IMGBTN_STATE_CHECKED_DISABLED);

修改图片状态为普通未按下状态

1
lv_imgbtn_set_state(menu_start, LV_IMGBTN_STATE_CHECKED_RELEASED);

修改图片状态为按下状态

1
lv_imgbtn_set_state(menu_start, LV_IMGBTN_STATE_CHECKED_PRESSED);

显示图片

1
lv_obj_clear_flag(img_warn_msg, LV_OBJ_FLAG_HIDDEN);

修改图片内容

将图片转换成C文件方式

1
2
3
4
//定义图片
LV_IMG_DECLARE(warn_cup_block);
//更改图片src
lv_img_set_src(img_warn_msg, &warn_cup_block);

将图片转换成bin文件方式:

1
2
//需要配合FatFS和提前将bin文件放到SD卡上
lv_img_set_src(img_warn_msg, "S:images/warn/warn_cup_block.bin");

手动触发事件

1
2
3
//下面2个函数手动触发事件
lv_event_send(btn1, USER_EVENT_1, &test_data);//内部调用lv_event_send_func
lv_event_send_func(btn_event_cb, btn1, LV_EVENT_REFRESH, &test_data1);

事件清单

 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
enum {
    LV_EVENT_PRESSED,             /**< The object has been pressed*/
    LV_EVENT_PRESSING,            /**< The object is being pressed (called continuously while pressing)*/
    LV_EVENT_PRESS_LOST,          /**< User is still pressing but slid cursor/finger off of the object */
    LV_EVENT_SHORT_CLICKED,       /**< User pressed object for a short period of time, then released it. Not called if dragged. */
    LV_EVENT_LONG_PRESSED,        /**< Object has been pressed for at least `LV_INDEV_LONG_PRESS_TIME`.  Not called if dragged.*/
    LV_EVENT_LONG_PRESSED_REPEAT, /**< Called after `LV_INDEV_LONG_PRESS_TIME` in every
                                       `LV_INDEV_LONG_PRESS_REP_TIME` ms.  Not called if dragged.*/
    LV_EVENT_CLICKED,             /**< Called on release if not dragged (regardless to long press)*/
    LV_EVENT_RELEASED,            /**< Called in every cases when the object has been released*/
    LV_EVENT_DRAG_BEGIN,
    LV_EVENT_DRAG_END,
    LV_EVENT_DRAG_THROW_BEGIN,
    LV_EVENT_GESTURE,           /**< The object has been gesture*/
    LV_EVENT_KEY,
    LV_EVENT_FOCUSED,
    LV_EVENT_DEFOCUSED,
    LV_EVENT_LEAVE,
    LV_EVENT_VALUE_CHANGED,      /**< The object's value has changed (i.e. slider moved) */
    LV_EVENT_INSERT,
    LV_EVENT_REFRESH,
    LV_EVENT_APPLY,  /**< "Ok", "Apply" or similar specific button has clicked*/
    LV_EVENT_CANCEL, /**< "Close", "Cancel" or similar specific button has clicked*/
    LV_EVENT_DELETE, /**< Object is being deleted */
    _LV_EVENT_LAST /** Number of events*/
};