【LVGL学习笔记】(二) 基础概念

LVGL全程LittleVGL,是一个轻量化的,开源的,用于嵌入式GUI设计的图形库。并且配合LVGL模拟器,可以在电脑对界面进行编辑显示,测试通过后再移植进嵌入式设备中,实现高效的项目开发。

LVGL中文教程手册:百问网LVGL中文教程手册文档

以下的内容均是以VS环境下的LVGL模拟器进行展开,之后会再针对移植的事项进行说明。

一. 框架

学过QT或者其他UI开发的选手应该了解:
UI界面就是由一个个控件,以及控件之间的相互关系(如父子继承关系,事件触发等)组成的。每个控件都有其独有的属性(如样式,触发函数等),LVGL也是如此。
LVGL还带有主题功能,能够便捷地统一控件样式。
因为是面向嵌入式设备进行开发,LVGL还需要有硬件相关的驱动。

// 主函数代码
int main(int argc, char** argv)
{	
	/*Initialize LittlevGL*/
	lv_init();

	/*Initialize the HAL for LittlevGL*/
	hal_init();

	/*
	 * Demos, benchmarks, and tests.
	 */
	 lv_demo();
	 
	while (1)
	{
		/* Periodically call the lv_task handler.
		* It could be done in a timer interrupt or an OS task too.*/
		lv_task_handler();
		Sleep(10);       /*Just to let the system breathe */
	}

	return 0;
}
  1. 对于功能实现,我们需要做的,就是将上面的lv_demo替换为我们自己写的函数。
  2. 因为lvgl内部是以不同线程的形式来处理各项任务,如刷屏等,并且我们也可以注册任务的,所以需要循环调用lv_task_handler来进行任务处理。
  3. lv_task_handler的调用除了在主函数的while中进行调用,也可以在OS或者定时器中断中进行调用,比如STM32使用FreeRTOS的一个线程进行处理。

二. 对象

对象具有各种属性,如位置尺寸等。
可以使用lv_obj_set _… 和 **lv_obj_get _…**来设置及获取属性信息。

/* 设置按键的大小 */
lv_obj_set_size(btn, 100, 50);   

/* 获取按键的父级指针 */
lv_obj_get_parent(btn)

不同控件的特殊属性可以使用带控件名称的函数进行实现。

/* 设置滑块的最小值和最大值 */
lv_slider_set_range(slider1, 0, 100);   

/* 设置回调函数 */
lv_slider_set_action(slider1, my_action);       

工作机制

1. 亲子结构
父对象可以作为其子对象的容器。每个对象只能一个父对象(屏幕除外),但是一个父对象可以有无限多个子对象。
父对象的类型没有限制,但是有特殊的父对象(例如,按钮)和特殊的子对象(例如,标签)。
2. 子对象仅在父对象的范围内可见
3. 子对象的位置是相对于父对象的位置,父对象移动时,两者相对位置不变。

创建和删除对象

/**
 * @param 指向父对象的指针。创建屏幕时以 NULL 作为父级。
 * @param 此参数可选,表示创建新对象时,把 copy 对象上的属性值复制过来
 */
lv_obj_t * lv_ <type>_create(lv_obj_t * parent, lv_obj_t * copy);

/* 所有对象类型都有一个通用的删除功能。它删除对象及其所有子对象 */
void lv_obj_del(lv_obj_t * obj);

/* 异步删除 */
void lv_obj_del_async(lv_obj_t * obj)

/*  删除对象的所有子对象(但不会删除对象本身) */
void lv_obj_clean(lv_obj_t * obj);

屏幕对象

/* 创建屏幕 */
lv_obj_t * scr = lv_obj_create(NULL, NULL);

/* 加载屏幕 */
lv_scr_load(scr)

/* 获取活动屏幕对象 */
lv_obj_t * scr = lv_scr_act()

/* 动态加载屏幕 */
/**
 * @brief 动态加载屏幕
 * @param transition_type 
 * LV_SCR_LOAD_ANIM_NONE 延迟x毫秒后立即切换
 * LV_SCR_LOAD_ANIM_OVER_LEFT/RIGHT/TOP/BOTTOM 将新屏幕移到给定方向上
 * LV_SCR_LOAD_ANIM_MOVE_LEFT/RIGHT/TOP/BOTTOM 将旧屏幕和新屏幕都移至给定方向
 * LV_SCR_LOAD_ANIM_FADE_ON 使新屏幕淡进旧屏幕
 * @time 转换时间
 * @delay 延迟时间
 * @auto_del 切换后是否删除旧屏幕
 */
lv_scr_load_anim(scr, transition_type, time, delay, auto_del)

多显示屏的使用

lv_scr_act() , lv_scr_load() 和 lv_scr_load_anim() 将会在默认显示屏幕上操作。

/* 以最后一个注册的显示设备作为默认显示屏幕 */
lv_disp_drv_register(lv_disp_drv_t * driver)

/* 选择新的默认显示屏幕 */
lv_disp_set_default(disp)

零件

对象部件一般都有多个零件。例如,按钮仅具有主要部分,而滑块则由背景,指示器和旋钮组成。我们可以对不同零件分别进行样式设计。
命名规则:LV_ + < TYPE > _ PART _ < NAME >
如:LV_BTN_PART_MAIN 、 LV_SLIDER_PART_KNOB

/* 设置容器样式 */
lv_obj_set_style_local_value_str(h, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, "Text input");

状态

/* 状态列表 */
LV_STATE_DEFAULT  // 默认或正常状态
LV_STATE_CHECKED  // 选中或点击
LV_STATE_FOCUSED  // 通过键盘或编码器聚焦或通过触摸板/鼠标单击
LV_STATE_EDITED   // 由编码器编辑
LV_STATE_HOVERED  // 鼠标悬停(现在还不支持)
LV_STATE_PRESSED  // 按下
LV_STATE_DISABLED // 禁用或无效
  1. 当用户按下,释放,聚焦等对象时,状态通常由库自动检测更改。
  2. 状态可以手动检测更改。
/* 完全覆盖当前状态 */ 
lv_obj_set_state(obj, part, LV_STATE...) 

/*设置或清除某个状态(但不更改其他状态) */ 
lv_obj_<add/clear>_state(obj, part, LV_STATE_...) 

/* 例:可以组合使用状态值 */
lv_obj_set_state(obj, part, LV_STATE_PRESSED | LV_PRESSED_CHECKED) .

三. 对象层级

规则:新创建的对象会覆盖旧对象进行显示。

/* 对象或它的任何子对象被点击,将自动将该对象带到最前面显示。*/
lv_obj_set_top(obj,true);

/* 对象或它的任何子对象被点击,将自动将该对象带到最后面。*/
lv_obj_move_foreground(obj);

/* 对象被带到新的父级对象前面 */
lv_obj_set_parent(obj,new_parent);

顶层和系统层

顶层:layer_top
系统层:layer_sys
两者在显示器的所有屏幕上都是可见且通用的,但是,它们不会在多个物理显示器之间共享。
位置:layer_top始终位于默认屏幕的顶部, layer_sys则位于layer_top的顶部。

/* 设置顶层可点击,其会吸收所有用户单击,也就是说其他控件都点不了了。*/
lv_obj_set_click(lv_layer_top(), true);

根据系统层的特性,可以将鼠标光标放在系统层,保持其一直可见。

四. 事件

多个对象可以使用一个回调函数

/* 指定一个事件回调函数 */
lv_obj_t * btn = lv_btn_create(lv_scr_act(), NULL);
lv_obj_set_event_cb(btn, my_event_cb);    

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;
}  

事件类型参考:事件(Events)

LV_EVENT_REFRESH是特殊事件,因为它旨在供用户用来通知对象刷新自身。如:

  1. 通知标签根据一个或多个变量(例如当前时间)刷新其文本
  2. 语言更改时刷新标签
/* 手动发布事件 */
lv_event_send(obj, LV_EVENT_..., &custom_data);

/* 发布刷新事件至对象 */
lv_event_send_refresh(obj);

/* 发布刷新事件至对象及其子对象 */
lv_event_send_refresh_recursive(obj);

五. 输入设备

设备类型:

  1. 指针式输入设备,如触摸板或鼠标
  2. 键盘,如普通键盘或简单的数字键盘
  3. 带有左/右转向和推入选项的编码器
  4. 外部硬件按钮,分配给屏幕上的特定点

指针

指针设备通常指鼠标

lv_indev_t * mouse_indev = lv_indev_drv_register(&indev_drv);
/* Declare the image file */
LV_IMG_DECLARE(mouse_cursor_icon); 
/* Create an image object for the cursor */
lv_obj_t * cursor_obj =  lv_img_create(lv_scr_act(), NULL);
/* Set the image source */ 
lv_img_set_src(cursor_obj, &mouse_cursor_icon); 
/* Connect the image  object to the driver */            
lv_indev_set_cursor(mouse_indev, cursor_obj);               

键盘和编码器

可以使用键盘和编码器选择对象,将像指针一样。所有想要通过键盘或编码器控制的对象需要添加到Group中。在每个组中,只有一个被聚焦的对象可以接收按下的键盘或编码器的动作。

/* 创建组 */
lv_group_t * g = lv_group_create()

/* 将对象添加进组 */
lv_group_add_obj(g, obj)

/* 关联组和设备 */
lv_indev_set_group(indev, g)

按键

/* 按键类型 */
LV_KEY_NEXT //专注于下一个对象
LV_KEY_PREV //专注于上一个对象
LV_KEY_ENTER //触发 LV_EVENT_PRESSED/CLICKED/LONG_PRESSED 等事件
LV_KEY_UP //增加值或向上移动
LV_KEY_DOWN //减小值或向下移动
LV_KEY_RIGHT //增加值或向右移动
LV_KEY_LEFT //减小值或向左移动
LV_KEY_ESC //关闭或退出(例如,关闭下拉列表)
LV_KEY_DEL //删除(例如,“ 文本”区域中右侧的字符)
LV_KEY_BACKSPACE //删除左侧的字符(例如,在文本区域中)
LV_KEY_HOME //转到开头/顶部(例如,在“ 文本”区域中)
LV_KEY_END //转到末尾(例如,在“ 文本”区域中)

其中,编码器仅使用 LV_KEY_LEFTLV_K​​EY_RIGHTLV_KEY_ENTER

编辑和导航模式
主要是针对编码器的应用。
LV_KEY_ENTER:切换编辑/浏览模式。
编辑模式:编码器左右旋为LV_KEY_LEFT/RIGHT
导航模式:编码器左右旋为LV_KEY_NEXT/PREV

状态
对象聚焦状态:LV_STATE_FOCUSED
对象编辑状态:LV_STATE_FOCUSED | LV_STATE_EDITED
因此需要设置这些状态下的样式,以区分对象状态。

六. 字体

字体属于是对象属性其中之一,可以通过设置对象样式的形式改变文本的字体样式。

/* Create a label on the second button */
lv_obj_t * label = lv_label_create(btn, NULL);        
lv_style_t my_style;
lv_style_init(&my_style);

/*Set a larger font*/
lv_style_set_text_font(&my_style, LV_STATE_DEFAULT, &lv_font_montserrat_28);

/* Add style to the objct */
lv_obj_add_style(label, LV_LABEL_PART_MAIN, &my_style);
lv_label_set_text(label, "Button"); 

字体样式

有几种不同大小的内置字体,可以通过 LV_FONT _… 定义在 lv_conf.h 中启用。启用后即可按照上述的格式进行字体样式调用。

/* 普通字体 */
LV_FONT_MONTSERRAT_<VAL> // VAL为12,14,16 ... 48,数值越大字体越大 

/* 特殊字体 */
LV_FONT_MONTSERRAT_12_SUBPX // 与常规12像素字体相同,但具有亚像素渲染
LV_FONT_MONTSERRAT_28_COMPRESSED // 与普通的28 px字体相同,但压缩字体为3 bpp
LV_FONT_DEJAVU_16_PERSIAN_HEBREW // 正常范围内的16像素字体+希伯来语,阿拉伯语,Perisan字母及其所有形式
LV_FONT_SIMSUN_16_CJK // 16 px字体,具有正常范围+ 1000个最常见的CJK部首
LV_FONT_UNSCII_8 // 仅包含ASCII字符的8 px像素完美字体

特殊符号

/* 直接调用 */
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);

七. 动画效果

可以使用动画在开始值和结束值之间自动更改变量的值。

/* 初始化动画 */
lv_anim_t a;
lv_anim_init(&a);

/* --- 必选设置 --- */

/* 设置“动画制作”功能 */
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t) lv_obj_set_x);

/* 设置“动画制作”功能 */
lv_anim_set_var(&a, obj);

/* 动画时长[ms] */
lv_anim_set_time(&a, duration);

/* 设置开始和结束值。例如。 0、150 */
lv_anim_set_values(&a, start, end);

/* --- 可选设置 --- */

/* 开始动画之前的等待时间[ms] */
lv_anim_set_delay(&a, delay);

/* 设置路径(曲线)。默认为线性 */
lv_anim_set_path(&a, &path);

/* 设置一个回调以在动画准备好时调用。 */
lv_anim_set_ready_cb(&a, ready_cb);

/* 设置在动画开始时(延迟后)调用的回调。 */
lv_anim_set_start_cb(&a, start_cb);

/* 在此持续时间内,也向后播放动画。默认值为0(禁用)[ms] */
lv_anim_set_playback_time(&a, wait_time);

/* 播放前延迟。默认值为0(禁用)[ms] */
lv_anim_set_playback_delay(&a, wait_time);

/* 重复次数。默认值为1。LV_ANIM_REPEAT_INFINIT用于无限重复 */
lv_anim_set_repeat_count(&a, wait_time);

/* 重复之前要延迟。默认值为0(禁用)[ms] */
lv_anim_set_repeat_delay(&a, wait_time);

/* true(默认):立即应用开始值,false:延迟设置动画后再应用开始值。真正开始。 */
lv_anim_set_early_apply(&a, true/false);

/* 应用动画效果 */
lv_anim_start(&a);                 

路径设置

lv_anim_path_linear  		// 线性动画
lv_anim_path_step 	 		// 一步到位
lv_anim_path_ease_in 		// 渐进效果
lv_anim_path_ease_out 		// 渐退效果
lv_anim_path_ease_in_out 	// 渐进和渐退效果
lv_anim_path_overshoot 		// 超出最终值
lv_anim_path_bounce 		// 从最终值反弹一点(就像撞墙一样)
/* 初始化路径 */
lv_anim_path_t path;
lv_anim_path_init(&path);
lv_anim_path_set_cb(&path, lv_anim_path_<type>);
lv_anim_path_set_user_data(&path, &foo); /* 自定义数据(可选) */

/* 在动画中设置路径 */
lv_anim_set_path(&a, &path);

速度设置

/* 将速度转换为时间再赋值 */
lv_anim_set_time(&a, lv_anim_speed_to_time(speed, start, end));

删除动画

lv_anim_del(var,func)
物联沃分享整理
物联沃-IOTWORD物联网 » 【LVGL学习笔记】(二) 基础概念

发表评论