LVGL学习笔记
LVGL的内部机制初探
lvgl的定时器处理程序负责管理并调度各种任务,以确保界面的流畅运行和响应性能。lvgl的定时器处理程序是一个内置的任务系统,允许开发者注册函数,使其可以定期被调用,帮主管理时间敏感的操作(毫秒级别)和周期性的活动。
注意:lvgl的定时器是非抢占式的。一旦一个定时器任务开始执行,它会运行直到函数退出,期间不会被其他定时器任务中断。因此,要确保注册的定时器任务不会运行太长时间,否则会影响整个系统的性能。
LVGL任务管理器的通俗理解:
int main(void)
{
// 制定两个时间规划:每隔1分钟喂一口饭;每隔一分钟回复一次消息
while (1)
{
// 看时钟判断:对比上次喂饭的时间,到了该喂饭的时间
喂一口饭();
记下这次喂饭的时间
// 看时钟判断:对比上次回消息的时间,到了该回消息的时间
回一个消息();
记下这次回消息的时间
}
}
LVGL部件学习
基础对象(简介1)
lvgl在初始化时就默认创建一个活动屏幕为基础对象。通过lv_scr_act()函数获取这个活动屏幕。
当创建了第一个部件后,之后的其他同类部件就有两个父对象可选:一种就是以你已经创建好了这个部件为父对象,再创建一个新对象;另一种是以活动屏幕来作为父对象
两个规律
- 当使用一个父对象创建一个子对象时,父对象就相当于子对象的一个容器,子对象是装在父对象里面的
- 利用父对象创建子对象时,子对象被创建时默认是在父对象的左上角
基础对象是所有控件的起源。
创建一个基本部件
基础对象(简介2)
LVGL对象的盒子模型
LVGL 遵循 CSS 的 border-box 模型。 对象的“盒子”由以下部分构成:
边界(bounding):元素的宽度/高度围起来的区域(整个盒子)。
边框(border):边框有大小和颜色等属性(相当于盒子的厚度和它的颜色)。
填充(padding):对象两侧与其子对象之间的空间(盒子的填充物)。
内容(content):如果边界框按边框宽度和填充的大小缩小,则显示其大小的内容区域(盒子实际装东西的区域)。
轮廓(outine):盒子之间的距离,取而代之的是轮廓(outline)。它是绘制于元素(盒子)周围的一条线,它不占据空间,位于边框边缘的外围,可起到突出元素(盒子)的作用。在浏览器里,当鼠标点击或使用Tab键让一个选项或者一个图片获得焦点的时候,这个元素就会多了一个轮廓框围绕。
LVGL的盒子模型是我们理解对象(部件)的组成,修改对象的样式,实现对对象的布局、处理对象排列等等的关键。
样式(重难点)
作用:样式用于设置部件的外观,以优化显示界面和实现用户交互。
添加普通样式
/* 创建一个部件 */
lv_obj_t * obj = lv_obj_create(lv_scr_act());
/* 设置部件的样式 */
lv_obj_set_style_bg_color(obj, lv_color_hex(0xf4b183),LV_STATE_DEFAULT);
解析第三个参数:
它是处于什么状态的时候会触发这一个设置的样式,
还可以设置这一个样式具体应用到这个部件的哪个部位
普通样式的优点:共享
添加本地样式:
缺点:只能应用到某一个部件上面,不能像普通样式进行共享
样式复习
① LVGL 样式的设置都是使用 lv_style_t 变量
② 在设置对象的样式时,可以指定在某个部分和状态下才生效。
③ 任何数量的对象都可以使用相同的样式。
④ 样式可以级联,这意味着用户可以将多个样式分配给同一个对象,并且每个样式可以
具有不同的属性
⑤ 样式具有优先级。如果两个函数同时设置某个属性,则最后调用的函数生效。
⑦ 对象样式设置的方法分为两种:普通样式和本地样式。注意:本地样式比普通样式的
优先级更高,所以 LVGL 会优先执行本地样式。
普通样式设置的最明显特点是:共用。
填充属性的作用:LVGL图形库中用来设置界面元素(比如按钮、文本框等)与其内容之间的空间距离
如何删除本地样式?
lv_obj_remove_local_style_prop(obj, LV_STYLE..., selector);
样式定义:用名称保存下来的对修饰对象进行修饰所用的一组修饰参数。
修饰对象:字符、段落、连接段落和字符、表格和表列
样式特点:
- 样式是一个lv_style_t变量、它可以保存边框的宽度、文本颜色等
- 样式可以级联即可以将多个分配给一个对象。LVGL优先使用我们定义的样式,如果没有就会使用默认值。
- 如果在两种样式中指定了同一个属性,则将使用最后添加的样式。
- 如果对象中并未指定某些属性(如文本颜色),就会从父级继承。
- 本地样式比正常样式具有更高的优先级。
- 默认有一个样式主题。
- 可以定义有过渡效果的样式。
如何使用样式?
初始化样式:
样式存储在lv_style_t类型的变量中。注意:样式必须设置为静态的、全局的或动态内存分配的。不能是函数的局部变量,因为函数结束时局部变量就被销毁了,样式就无法起效了。
static lv_style_t my_style;
lv_style_init(&my_style);
设置样式属性
lv_style_set_bg_color(&my_style, lv_color_hex(0x00ff00));
lv_style_set_bg_opa(&my_style, LV_OPA_50);
添加样式到对象中,接口函数如下:
lv_obj_add_style(obj, &my_style, <selector>);
删除对象的所有样式:
lv_obj_remove_style_all(obj);
删除对象的特定样式:
lv_obj_remove_style(obj, &style_obj, selector);
注意:只有当selector与lv_obj_add_style()中使用的selector匹配时,此函数才会删除style
如果style是空的,那么会根据给出的selector检查并删除所有匹配的样式。
事件
相关API
-
添加事件
// 函数功能: // 允许你为LVGL对象(如按钮、滑动条、标签等)添加事件回调函数。 // 这个函数允许你指定在特定事件发生时应该调用的函数,以及传递给该函数的额外数据 lv_obj_add_event_cb(obj, event_cb, event_code, user_data);
参数解析:
- event_cb:这是一个函数指针,指向你定义的事件回调函数。当指定的事件发生时,这个函数将被自动调用。
- event_code:这是一个宏或枚举值,指定了你想要监听的事件类型。LVGL定义了多种事件类型,比如点击(
LV_EVENT_CLICKED
)、值改变(LV_EVENT_VALUE_CHANGED
)、长按(LV_EVENT_LONG_PRESSED
)等。 - user_data:这是一个可选的指针,你可以传递任何自定义的数据给事件回调函数。这个数据在事件发生时不会被LVGL修改或解释,它只是简单地传递给回调函数,以便你在回调函数中根据需要使用它。如果你不需要传递任何自定义数据,可以传递
NULL
。
-
删除事件
lv_obj_remove_event_cb(obj, event_cb);
事件与对象之间的关系:
不同的事件类型共用一个事件回调函数怎么处理?
第一步,使用lv_event_code()函数获取事件类型
第二步,判断事件类型并执行相关操作
static void event_cb( lv_event_t *e )
{
/* 第一步:获取事件类型 */
lv_event_code_t code = lv_event_get_code(e);
if ( code == LV_EVENT_CLICKED ) /* 第二步:判断事件类型 */
{
printf(“事件类型: 按下后释放\r\n”);
/* 第三步:执行相应操作 */
}
else if ( code == LV_EVENT_LONG_PRESSED)
{
printf(“事件类型:按下(长按)\r\n”);
}
}
不同的部件共用一个事件回调函数怎么处理?
第一步,获取事件的触发部位
第二步,判断事件的触发部位并执行相应操作
static void event_cb( lv_event_t *e )
{
/* 第一步:获取触发事件的部件 */
lv_obj_t *target = lv_event_get_target(e);
if ( target == parent_obj ) /* 第二步:判断触发事件的部件 */
{
printf(“父对象触发事件 \r\n”);
/* 第三步:执行相应操作 */
}
else if ( target == child_obj )
{
printf(“子对象触发事件 \r\n”);
}
}
添加事件
lv_obj_add_event_cb(obj, event_cb, event_code, user_data);
发送事件:用于向对象发送事件。简单来说就是触发回调函数
函数原型如下:
lv_res_t lv_obj_send_event(lv_obj_t * obj,
lv_event_code_t event_code,
void * param);
删除事件
获取事件传递的用户数据:
lv_event_get_user_data(e) ;该函数用于获取lv_obj_add_event_cb()函数传递的用户数据。
lv_event_get_param(e);该函数获取使用lv_obj_send_event()函数传递的用户数据。
获取最初触发事件的对象?
lv_obj_t* target = lv_event_get_current_target(e);
事件冒泡:
如果对象启用了lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE)
, 该对象的所有事件将会发送到该对象的父级。如果父级对象也启用了LV_OBJ_FLAG_EVENT_BUBBLE
,那么事件继续发送到他的父级,以此类推。
lv_event_get_target(e)
获取触发事件的当前对象lv_event_get_current_target(e)
获取事件冒泡的父对象
LVGL定时器(lv_timer) 入门
LVGL的定时器就是会按照指定周期(单位:毫秒ms)执行的函数。LVGL有一个内置的计时器系统。我们可以注册一个函数,让它定期被调用,这个函数我们可以称之为定时器处理任务。这些定时器任务在 Iv_task_handler()中进行处理和调用,需要每隔x毫秒调用一次。
定时器是非抢占式的,这也就是说一个定时器不能中断另一个定时器。因此,我们可以在定时器回调函数中调用任何与LVGL相关或无关的函数。
使用定时器
1.创建定时器 :
lv _timer_t * timer = lv_timer create(timer_cb, period_ms, user data);
可以通过 Iv_timer_create 返回的定时器句柄”timer“ 变量,修改定时器的参数。
timer_cb:定时器回调函数原型:
void (*Iv timer cb t)(lv timer t*)
period ms:定时器执行周期,以毫秒(ms)为单位
user data:用户数据,void*类型的指针
动画的本质是定时器的处理。
标签
在 LVGL 中,标签部件主要用于文本显示,例如标题、提示信息等。
设置文本的第二种方式产生两个问题:
1. 所指定的缓冲区里面的内容被修改或是这个内存被释放掉了那么从这个缓冲区获取的数据将是不可靠的
1. 如果缓冲区是只读的,当对缓冲区进行写操作时那么程序崩溃
标签部件组成部分:
- 标签部件组成部分
- 滚动条(LV_PART_SCROLLBAR)
- 选中的文本(LV_PART_SELECTED)
如何创建标签部件以及设置文本?
-
创建标签部件
lv_obj_t* label = lv_label_create(lv_scr_act());
-
设置文本的3种方式
-
直接设置文本,存储文本的内存动态分配
lv_label_set_text( label, "hallo \n lvgl");
-
文本不存储在动态内存,而是在指定的缓冲区中(慎用)。因为这些文本存储在代码段中,而代码段属于只读的。如果在后面的操作中修改了文本内容,则程序崩溃。
```c lv_label_set_text_static(label, "hallo"); ```
-
格式化显示文本
lv_label_set_text_fmt( label, “Value: %d”, 50);
-
改变文本样式?
设置文本样式
-
背景颜色
// 默认情况下,对于标签的部件来说,背景透明度是完全透明的 // 因此要先设置透明度,才可以显示背景颜色 // 设置背景的透明度 lv_obj_set_style_bg_opa(label, 100, LV_STATE_DEFAULT); // 设置背景颜色 lv_obj_set_style_bg_color(label, lv_color_hex(0xff0000), LV_STATE_DEFAULT);
-
字体大小
lv_obj_set_style_text_font(label, &lv_font_montserrat_30,// 30号字体 LV_STATE_DEFAULT);
-
文本颜色
lv_obj_set_style_text_color(label, lv_color_hex(0x5084db), LV_STATE_DEFAULT);
设置个别文本的字体颜色
// 注意:要对个别字体设置特定颜色必须开启重新着色的功能
/* 开启重新着色功能 */
lv_label_set_recolor(label, true);
/* 单独设置颜色 */
// 注意:16进制的颜色值与设置特定颜色的文本要有一个空格
lv_label_set_text(label, "hallo #ff0000 lvgl#");// 給lvgl单独设置颜色
标签内部的文本对齐方式
lv_obj_set_style_text_align(obj, align, LV_STATE_DEFAULT);
解析第二个参数lv_text_align_t
枚举值:
lv_text_align_t
枚举包含以下值,用于定义不同的文本对齐方式:
LV_TEXT_ALIGN_LEFT
:文本左对齐。在水平方向上,文本将从对象的左侧开始显示。LV_TEXT_ALIGN_CENTER
:文本居中对齐。在水平方向上,文本将位于对象的中心位置。LV_TEXT_ALIGN_RIGHT
:文本右对齐。在水平方向上,文本将从对象的右侧开始显示。LV_TEXT_ALIGN_AUTO
:自动对齐。这个选项通常用于文本换行时的对齐。在水平方向上,它可能表现为左对齐、居中对齐或右对齐,具体取决于对象的宽度和文本内容。在垂直方向上,它通常意味着文本会根据对象的高度进行垂直居中。
当文本长度超过部件大小的时候怎么显示?
-
情况一:默认情况下,如果没有限定标签部件大小,那它的大小自动扩展为文本大小。
-
长文本模式
lv_label_set_long_mode(label, LV_LABEL_LONG_...); // 第二个参数的取值 enum { /* 默认模式, 如果部件大小已固定,超出的文本将被剪切 */ LV_LABEL_LONG_WRAP, /* 将 label 右下角的最后 3 个字符替换为点… */ LV_LABEL_LONG_DOT, LV_LABEL_LONG_SCROLL, /* 来回滚动 */ LV_LABEL_LONG_SCROLL_CIRCULAR, /* 循环滚动 */ /* 直接剪切掉部件外面的文本部分 */ LV_LABEL_LONG_CLIP, };
lv_obj_set_style_text_align()
是 LVGL 中用于设置对象文本对齐方式的函数。它可以控制文本在对象内部的水平对齐方式(左对齐、居中对齐、右对齐)。这个函数适用于所有支持文本显示的对象,例如标签(lv_label
)、按钮(lv_btn
)等。
void lv_obj_set_style_text_align(
lv_obj_t* obj, // 目标对象
lv_text_align_t align, // 文本对齐方式
lv_style_selector_t selector // 样式选择器
);
按钮
按钮部件组成部分:主体(LV_PART_MAIN)
知识点1:创建按钮部件
// 在活动屏幕中创建一个按钮,默认放在屏幕的左上角
lv_obj_t* btn = lv_btn_create(lv_src_create());
知识点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(0xffe1d4), LV_STATE_PRESSED );
知识点3:添加事件
/* 开启状态切换 */
lv_obj_add_flag( btn, LV_OBJ_FLAG_CHECKABLE );
// 这行代码的作用是为btn对象添加一个事件回调函数event_cb
// 该函数将在btn对象的值改变时被调用
lv_obj_add_event_cb( btn, event_cb, LV_EVENT_VALUE_CHANGED,NULL );
解析:
lv_obj_add_flag 函数用于给LVGL对象(如按钮、标签等)添加特定的标志(flag),
以改变其行为或外观。
LV_OBJ_FLAG_CHECKABLE 标志的作用
- 可勾选(Checkable):当给对象(如按钮)添加
LV_OBJ_FLAG_CHECKABLE
标志后,该对象就变成了一个可勾选(或可切换状态)的控件。对于按钮来说,这通常意味着用户可以通过点击来切换按钮的“选中”和“未选中”状态。 - 状态切换:默认情况下,按钮可能只响应点击事件来执行某些动作(如调用回调函数)。但添加了
LV_OBJ_FLAG_CHECKABLE
后,按钮会记住它的状态(选中或未选中),并且可以根据需要改变其外观(如显示勾选标记)来反映其当前状态。 - 外观变化:通常,LVGL会根据控件的状态(如是否选中)自动调整其外观。对于按钮来说,这可能意味着在选中状态下,按钮的背景色、边框或图标会发生变化,以向用户表明其当前状态。
第三个参数LV_EVENT_VALUE_CHANGED
是一个枚举值,用于指定要监听的事件类型。在LVGL中,事件系统允许开发者为对象定义和监听各种事件,以便在特定条件满足时执行自定义代码。
LV_EVENT_VALUE_CHANGED
是一个特定的事件类型,它通常在对象的值或状态发生变化时被触发。对于不同类型的对象,这个“值”的含义可能不同:
- 对于滑块(Slider)或滚动条(Scrollbar),这通常意味着用户通过拖动改变了滑块的位置,从而改变了其值。
- 对于复选框(Checkbox)或开关(Switch),这表示用户通过点击改变了其选中/未选中的状态。
- 对于按钮(Button),虽然按钮通常不直接关联到一个“值”,但如果你将按钮的点击视为一种“状态”的变化(即从未点击到点击),并且你通过某种方式(如变量)来跟踪这种变化,那么理论上你也可以为按钮的点击事件使用
LV_EVENT_VALUE_CHANGED
(尽管更常见的做法是直接使用LV_EVENT_CLICKED
)。然而,在标准用法中,按钮的点击通常是通过LV_EVENT_CLICKED
事件来处理的。
开关
功能:开关部件常用于控制某个功能的开启和关闭,它可以直接显示被控对象的状态。
开关的组成部分
- 主体:LV_PART_MAIN
- 手柄:LV_PART_KNOB
- 指示器:LV_PART_INDICATOR
步骤:
-
创建开关部件
lv_obj_t* switch1 = lv_switch_create(parent);
-
添加或清除开关状态
lv_obj_add_state(switch1, LV_STATE_CHECKED)// 添加状态 lv_obj_clear_state(switch1, LV_STATE_CHECKED)// 清除状态
LV_STATE_CHECKED
:这是一个预定义的状态标志,用于表示对象的选中状态。在LVGL中,这个标志通常用于表示复选框(checkbox)或开关(switch)对象是否被激活或选中。
-
获取(判断)开关状态
lv_obj_has_state(switch1, LV_STATE_CHECKED) // 返回值是布尔类型,开则返回真,关则返回假
设置开关的大小时,宽度和高度比例最好是(2,1)
复选框
功能:复选框部件常用于选择某个内容的开启和关闭,可以理解为自带标签的开关。
复选框的组成部分
- 主体:LV_PART_MAIN
- 勾选框:LV_PART_INDICATOR
创建复选框
lv_obj_t* checkbox = lv_checkbox_create(parent);
文本设置
lv_checkbox_set_text(checkbox, "text");// 设置文本内容
// 设置复选框和文本的间距
lv_obj_set_style_pad_column(checkbox, 20, LV_STATE_DEFAULT);
添加或清除复选框状态
/* 添加状态:默认选中且不可修改 */
lv_obj_add_state(checkbox, LV_STATE_CHECKED | LV_STATE_DISABLED);
/* 清除复选框的状态 */
lv_obj_clear_state(checkbox, LV_STATE_CHECKED | LV_STATE_DISABLED);
判断(获取)复选框的状态
/* 返回值:1,选中; 0,非选中 */
lv_obj_has_state(checkbox, LV_STATE_CHECKED);
进度条
功能:进度条部件常用于显示当前任务的完成进度。
组成
- 主体:LV_PART_MAIN
- 指示器:LV_PART_INDICATOR
知识点1:创建进度条部件
lv_obj_t* bar = lv_bar_create(parent);
知识点2:设置大小、当前值、范围值
lv_obj_set_size( bar, 400, 20 ); /* 设置大小 */
lv_bar_set_range( bar, -100, 100 ); /* 设置范围值 */
lv_bar_set_value( bar, 50, LV_ANIM_ON ); /* 设置当前值 */
解析上述三行代码:
-
对于上述三行代码而言,虽然开启了动画效果,但是因为动画时间太短了,无法观察到动画。
-
注意:默认创建出来的进度条,在lv8.2版本中值的范围是1~ 100;在lv9版本中值的范围是0 ~ 100。换句话说,进度条的初始值取决于lvgl的版本
-
范围值的设置必须放在设置当前值的前面。
lv_bar_set_value()函数的第三个参数是一个动画控制标志,用于指定在改变值时是否应该应用动画效果。
第三个参数:用于控制动画的开启或关闭。
知识点3:设置动画时间
动画设置必须放在当前值设置之前
lv_obj_set_style_anim_time( bar, 500, LV_STATE_DEFAULT );
解析:第二个参数指定了动画的持续时间,单位是毫秒。这表明, 当bar
对象的状态发生变化(比如从不可见变为可见,或者值的变化导致视觉上的更新)时,这个变化将在500毫秒内平滑过渡完成。
知识点4:设置模式、起始值
lv_bar_set_mode( bar, LV_BAR_MODE_RANGE ); /* 设置模式 */
lv_bar_set_start_value( bar, -50, LV_ANIM_OFF ); /* 设置起始值 */
enum {
LV_BAR_MODE_NORMAL, /* 默认模式 */
// 从零值绘制到当前值(当前值可以小于0)该模式下不允许设置起始值
LV_BAR_MODE_SYMMETRICAL,
// 允许设置起始值,但起始值必须小于当前值
LV_BAR_MODE_RANGE,
};
进度条使用的注意事项
- 当进度条高度大于宽度时,其方向变为垂直。
- 动画时间设置需要放在当前值设置之前 ,否则看不到动画效果。
- 动画时间指的是旧值刷新到新值的绘图时间,并不是现实中当前值变化所需的时间。
注意:在V8.2版本的LVGL中,默认模式也允许设置起始值,但是后续的版本可能会修改。
因此,在设置进度条的起始值时,最好先使用LV_BAR_MODE_RANGE模式。
加载器
功能:加载器部件常用于提示当前任务正在加载。
加载器部件组成:
- 主体:LV_PART_MAIN
- 指示器:LV_PART_INDICATOR
- 手柄:LV_PART_KNOB
创建加载器部件:
lv_obj_t* spinner = lv_spinner_create(parent, spin_time, arc_length );
第二参数表示指示器旋转一圈的时间(以毫秒为单位)。
第三个参数表示arc_length 形参表示指示器的长度。
设置圆弧颜色
/* 设置主体圆弧颜色 */
lv_obj_set_style_arc_color( spinner,
lv_color_hex(0x4a9f00),
LV_PART_MAIN );
/* 设置指示器圆弧颜色 */
lv_obj_set_style_arc_color(spinner,
lv_color_hex(0x83bd55),
LV_PART_INDICATOR);
设置圆弧宽度
/* 设置主体圆弧宽度 */
lv_obj_set_style_arc_width( spinner, 30, LV_PART_MAIN );
/* 设置指示器圆弧宽度 */
lv_obj_set_style_arc_width( spinner, 30, LV_PART_INDICATOR );
LED部件
注意:打开、关闭LED时,亮度不绝对是255、0,具体要看相关的宏定义(可修改)
功能:LED部件常用于指示控制对象的状态。
组成部分:主体(LV_PART_MAIN)
创建LED部件
lv_obj_t *led = lv_led_create(parent);
设置LED颜色、l亮度
lv_led_set_color( led, lv_color_hex(0xff0000) ); /* 设置LED颜色 */
lv_led_set_brightness( led, 0 ); /* 设置LED亮度,范围0~255*/
设置LED状态
/* 打开LED(设置亮度为255)*/
lv_led_on( led );
/* 关闭LED */
lv_led_off( led );
/* 翻转LED状态 */
lv_led_toggle( led );
列表
功能:列表部件常用于多选一的场景,默认会展现多个选项。
列表组成:
- 主体:LV_PART_MAIN
- 滚动条:LV_PART__SCROLLBAR
创建列表部件
lv_obj_t* list = lv_list_create( parent );
知识点2:添加列表文本
lv_list_add_text( list, “Settings" );
知识点3:添加列表按钮
lv_obj_t *btn= lv_list_add_btn( list, LV_SYMBOL_WIFI, “WLAN");
知识点4:获取列表按钮文本
lv_list_get_btn_text( list, list_btn );
下拉列表
功能:下拉列表部件常用于多选一的场景,点击后可展现多个选项。
组成:
- 按钮:BUTTON
- 列表:LIST
知识点1:创建下拉列表
lv_obj_t *dd = lv_dropdown_create( parent );
知识点2:设置选项内容
/* 设置选项 */
lv_dropdown_set_options( dd, "a\nb\nc\nd");
/* 设置选项 (静态)*/
lv_dropdown_set_options_static( dd, "a\nb\nc\nd ");
/* 添加选项,索引从0开始 */
lv_dropdown_add_option( dd, "e", 4);
解析第二个函数
lv_dropdown_set_options_static()
函数的作用是为指定的下拉列表控件设置一组静态的选项。这些选项在下拉列表创建后不会改变,除非你再次调用此函数来更新它们。
使用 lv_dropdown_set_options_static()
函数适用于以下场景:
- 当下拉列表的选项在程序运行期间是固定不变的,例如,一个包含预定义设置选项的配置菜单。
- 你希望下拉列表的选项在程序启动时就完全确定,并且在程序运行期间不需要动态添加或删除选项。
- 这对于创建具有固定选项的下拉菜单非常有用,可以简化界面设计并减少运行时的资源消耗。
知识点3:设置当前所选项
lv_dropdown_set_selected( dd, 1); /* 注意:索引从0开始 */
知识点4:获取选项内容
lv_dropdown_get_selected( dd); /* 获取索引 */
char buf[10];
lv_dropdown_get_selected_str( dd, buf, sizeof(buf)); /* 获取选项文本 */
知识点5:设置方向和图标
lv_dropdown_set_dir(dd, LV_DIR_RIGHT); /* 设置列表展开方向 */
lv_dropdown_set_symbol(dd, LV_SYMBOL_RIGHT); /* 设置图标 */
滚轮
功能:滚轮部件常用于多选一的场景,它以滚轮的形式来展现多个选项。
滚轮组成部分:
- 主体:LV_PART_MAIN
- 选项框:LV_PART_SELECTED
知识点1:创建滚轮部件
lv_obj_t *roller= lv_roller_create( parent );
知识点2:设置选项间隔
lv_obj_set_style_text_line_space(roller, 30, LV_STATE_DEFAULT);
知识点3:设置选项内容、滚动模式
/* 正常模式 */
lv_roller_set_options(roller, “a\nb\nc\nd”, LV_ROLLER_MODE_NORMAL);
// 无限循环模式:占用内存较大
lv_roller_set_options(roller, "a\nb\nc\nd", LV_ROLLER_MODE_INFINITE);
知识点4:设置当前所选项
lv_roller_set_selected(roller, 3, LV_ANIM_ON);
知识点5:设置可见行数
lv_roller_set_visible_row_count(roller, 2);
知识点6:获取选项内容
lv_roller_get_selected(roller); /* 获取索引 */
char buf[10];
/* 获取选项文本 */
lv_roller_get_selected_str(roller, buf, sizeof(buf));
滑块
功能:滑块部件常用于调节某个参数的值,它以直线滑动的形式来修改数值。
滑块部件组成部分:
- 主体:LV_PART_MAIN
- 指示器:LV_PART_INDICATOR
- 旋钮:LV_PART_KNOB
知识点1:创建滑块部件
lv_obj_t *slider = lv_slider_create( parent );
知识点2:设置大小、当前值、范围值
lv_obj_set_size(slider, 20, 200); /* 高度>宽度时,滑块为纵向 */
lv_slider_set_value(slider, 50, LV_ANIM_OFF); /* 设置当前值 */
lv_slider_set_range(slider, -100, 100); /* 设置范围值 */
知识点3:获取当前值
lv_slider_get_value(slider);
知识点4:模式设置
lv_slider_set_mode(slider, LV_SLIDER_MODE_...);
知识点5:设置、获取左值
lv_slider_set_left_value(slider, 20, LV_ANIM_OFF); /* 设置左值 */
lv_slider_get_left_value(slider); /* 获取左值 */
注意:在模式设置中,对于LV_SLIDER_MODE_SYMMETRICAL,滑块总是从零开始绘制
移除滑块的旋钮
lv_obj_remove_style(slider, NULL, LV_PART_KNOB);
圆弧
功能:圆弧部件以弧形滑动的形式来调节、显示某个参数的值。
圆弧部件组成部分:
- 背景弧:LV_PART_MAIN
- 前景弧:LV_PART_INDICATOR
- 旋钮:LV_PART_KNOB
知识点1:创建圆弧部件
lv_obj_t *arc = lv_arc_create( parent );
知识点2:设置当前值、范围值
lv_arc_set_value(arc, 80); /* 设置当前值(需要在范围值之内)*/
lv_arc_set_range(arc, 0, 200); /* 设置范围值 */
知识点3:设置圆弧角度
lv_arc_set_angles(arc, 135, 270); /* 设置前景弧角度 */
lv_arc_set_bg_angles(arc, 135, 45); /* 设置背景弧角度 */
知识点4:设置旋转角度
lv_arc_set_rotation(arc, 180);
知识点5:获取当前值
lv_arc_get_value(arc);
知识点6:设置模式、圆弧绘制速率
lv_arc_set_mode(arc, LV_ARC_MODE_REVERSE); /* 设置模式 */
lv_arc_set_change_rate(arc, 90); /* 绘制速率:90°/秒 */
重要的注意事项:
-
背景弧的默认起始角度是135度
-
背景弧角度设置必须放在前景弧角度之前。
-
前景弧角度设置的范围必须包含在背景弧角度设置的范围内。
-
当前景弧的起始角度大于背景弧的起始角度,如果修改当前值时,lgvl就会强制修改前景弧的起始角度,把前景弧的起始角度更改为背景弧的起始角度。
-
设置前景弧的函数尽量不要使用。
-
如果只是仅仅调用前景弧函数去设置圆弧,但是当前值是不会跟着前景圆弧变化的。
因此当前值设置和前景弧设置函数不要混用。简单来说,就是图和值对不上的问题。
线条
功能:线条部件能够在一组坐标点之间依次绘制直线。
组成部分:主体(LV_PART_MAIN)
知识点1:创建线条部件
// 注意仅使用该函数则默认没有任何显示
lv_obj_t *line = lv_line_create( parent );
知识点2:设置线条坐标点
static lv_point_t line_points[] = { {15, 5}, {25, 20}, {5, 20}, {15, 5} };
lv_line_set_points(line, line_points, 4);
知识点3:设置线条样式
lv_obj_set_style_line_width(line, 8, LV_PART_MAIN); /* 设置宽度 */
lv_obj_set_style_line_rounded(line, true, LV_PART_MAIN); /* 设置圆角 */
知识点4:设置y轴反转
lv_line_set_y_invert(line, true);
如何使用线条部件绘制曲线?关键在于获取曲线的坐标。
图片
默认情况下,都是中心点进行旋转和缩放的。
对于lv_img_set_pivot()函数来说,中心点是相对于原照片来说的。
功能:图片部件可用于图片显示、功能界面优化、背景优化等。
图片部件组成部分:主体(LV_PART_MAIN)
知识点1:创建图片部件
lv_obj_t *img = lv_img_create( parent );
知识点2:设置图片源
LV_IMG_DECLARE(img_bird); /* 声明图片 */
lv_img_set_src(img, &img_bird); /* 设置图片源 */
知识点3:设置图片偏移
// 多出来的地方回到左侧
lv_img_set_offset_x(img, 100); /* x轴偏移100 */
// 多出来的地方回到右侧
lv_img_set_offset_y(img, 20); /* y轴偏移20 */
知识点4:图片重新着色
能对图片的整体进行着色, 但不能对部件的某个部分进行着色。
首先设置透明度,然后再着色。
lv_obj_set_style_img_recolor(img, lv_color_hex(0xffe1d2),LV_PART_MAIN);
lv_obj_set_style_img_recolor_opa(img, 150, LV_PART_MAIN);
知识点5:设置图片缩放、旋转
lv_img_set_zoom(img, 512); /* 放大2倍 */
lv_img_set_angle(img, 900); /* 顺时针方向旋转90° */
知识点6:设置中心点
lv_obj_update_layout(img); /* 更新图片布局信息 */
lv_img_set_pivot(img, 0, 0); /* 设置中心点 */
色环
功能:在UI设计中,色环部件一般用作颜色选择器。
组成:
- 主体:LV_PART_MAIN
- 旋钮:LV_PART_KNOB
知识点1:创建色环部件
lv_obj_t *cw = lv_colorwheel_create( parent, knob_recolor );
知识点2:设置当前选中颜色
lv_colorwheel_set_rgb(cw, lv_color_hex(0xff0000));
知识点3:获取当前选中颜色
lv_colorwheel_get_rgb(cw);
知识点4:设置色环模式
lv_colorwheel_set_mode(cw, LV_COLORWHEEL_MODE_HUE/SATURATION/VALUE);
/* 色相、饱和度、明度 */
lv_colorwheel_set_mode_fixed(cw, true);
/* 固定色环模式 */
设置圆角
void lv_obj_set_style_radius(struct _lv_obj_t * obj,
lv_coord_t value, lv_style_selector_t selector);
// 该函数用来设置圆角第二参数表示圆角值
按钮矩阵
按钮互斥是指在同一按钮矩阵中,多个按钮之间具有排他性。当用户点击一个按钮时,该按钮会被激活,而之前激活的按钮会自动取消激活。
在 LVGL 中,按钮矩阵的互斥功能是通过设置按钮的 控制映射(Control Map) 来实现的。每个按钮可以配置一个控制标志(Control Flag),用于定义其行为。
功能:按钮矩阵部件可以在不同的行和列中显示多个轻量级按钮。
组成:
- 主体(LV_PART_MAIN)
- 按钮(LV_PART_ITEMS)
知识点1:创建按钮矩阵部件
lv_obj_t *btnm = lv_btnmatrix_create(parent);
知识点2:设置按钮数量、文本
/* 定义按钮数组,最后一个元素必须为空 */
static const char *map[] = { "btn1", "\n", "btn2", "btn3", "" };
/* 设置按钮 */
lv_btnmatrix_set_map(btnm, map);
如果需要让按钮换行,可以在字符串数组中使用换行符“\n”。注意:换行符必须独立成一个字符即换行符前面以及后面不可以有字符。
知识点3:设置按钮相对宽度
/* 索引 (id) 从0开始,宽度1~7 ( 默认为1 ) */
lv_btnmatrix_set_btn_width(btnm, id, width);
注意:在按钮矩阵部件中,按钮只能设置相对宽度。
知识点4:获取按钮索引、文本
lv_btnmatrix_get_selected_btn(btnm); /* 获取索引 */
lv_btnmatrix_get_btn_text(btnm, id); /* 获取文本 */
索引就相当于一个 ID,在按钮矩阵部件中,每一个按钮都有对应的索引。索引从零开始。
知识点5:设置、清除按钮属性
/* 设置单个按钮属性 */
lv_btnmatrix_set_btn_ctrl(btnm, id, LV_BTNMATRIX_CTRL_...);
/* 清除单个按钮属性 */
lv_btnmatrix_clear_btn_ctrl(btnm, id, LV_BTNMATRIX_CTRL_...);
/* 设置所有按钮属性 */
lv_btnmatrix_set_btn_ctrl_all(btnm, LV_BTNMATRIX_CTRL_...);
enum {
LV_BTNMATRIX_CTRL_HIDDEN, /* 隐藏 */
LV_BTNMATRIX_CTRL_DISABLED, /* 失能 */
LV_BTNMATRIX_CTRL_CHECKABLE, /* 允许状态切换 */
LV_BTNMATRIX_CTRL_RECOLOR, /* 允许文本重新着色 */
};
对于 LV_BTNMATRIX_CTRL_CHECKABLE,若不设置这个属性值,在默认的情况下,按了某个按钮并释放掉后这个按钮就恢复为没按下的状态。若设置了这个值,则点击某个按钮并释放后,按钮的状态保持不变而且其他按钮不能保持状态。
按钮的文本默认是黑色的。
知识点6:设置单次选中属性
按钮互斥:按钮互斥是指:在某一时刻,只允许有一个按钮处于按下不弹起状态(被选中),当我们
选中一个按钮之后,其他的按钮将会自动清除选中属性。
通俗说法:一旦有某个按钮被选中后,那么其他按钮都会变成未选中的状态。每次点击中,只有一个按钮被选中,其他按钮都变成未选中状态。
注意:要设置单次选中属性,需要先给按钮设置允许状态切换属性。
lv_btnmatrix_set_one_checked(btnm, true);// 开启按钮互斥
第48个视频:例程讲解
移除滚动条
lv_obj_remove_style(obj_input, NULL, LV_PART_SCROLLBAR);
按钮矩阵部件的事件
① LV_EVENT_VALUE_CHANGED:当一个按钮被按下、释放或长按时发送。
② LV_EVENT_DRAW_PART_BEGIN:开始绘制按钮。
文本区域
文本区域部件组成部分:
- 主体(LV_PART_MAIN)
- 滚动条(LV_PART_SCROLLBAR)
- 所选文本(LV_PART_SELECTED)
- 光标(LV_PART_CURSOR)
- 占位符(TEXTAREA_PLACEHOLDER)
知识点1:创建文本区域部件
lv_obj_t *ta = lv_textarea_create(parent);
知识点2:添加文本
// 方法一:直接设置文本
lv_textarea_add_char(ta, 'A'); /* 添加一个字符到当前光标处 */
lv_textarea_add_text(ta, "BCDEF"); /* 添加字符串到当前光标处 */
// 方法二:设置键盘输入
lv_obj_t *keyboard = lv_keyboard_create(lv_scr_act());/* 创建键盘部件 */
lv_keyboard_set_textarea(keyboard, ta); /* 关联键盘和文本区域部件 */
知识点3:设置光标位置
/* 0:最左侧;LV_TEXTAREA_CURSOR_LAST:最右侧 */
lv_textarea_set_cursor_pos(ta, 0);
知识点4:删除文本
lv_textarea_del_char(ta); /* 删除光标左侧的一个字符 */
lv_textarea_del_char_forward(ta); /* 删除光标右侧的一个字符 */
知识点5:设置模式
lv_textarea_set_one_line(ta, true); /* 单行模式 */
lv_textarea_set_password_mode(ta, true); /* 密码模式(隐藏输入的内容) */
lv_textarea_set_password_show_time(ta, 100); /* 密码显示时间 */
知识点6:限制字符输入
lv_textarea_set_accepted_chars(ta,"0123456789"); /* 限制接收的字符 */
lv_textarea_set_max_length(ta,6); /* 限制字符长度 */
知识点7:设置占位符
lv_textarea_set_placeholder_text(ta, "password"); /* 提示输入密码 */
知识点8:获取文本
const char *txt = lv_textarea_get_text(ta); /* 获取文本框文本 */
知识点9:比对文本内容
strcmp(const char *s1,const char *s2); /* 当s1=s2时,返回0 */
strncmp(const char* s1, const char* s2, size_t size);
LV_EVENT_FOCUS
是一个事件类型,它表示某个界面元素(比如按钮、输入框等)获得了用户的关注,即它成为了当前可以接收输入或操作的元素。这个事件通常与键盘导航或触摸屏输入相关联。
键盘
功能:键盘部件可用于输入文本内容,其本质上就是一个特殊的按钮矩阵。
键盘部件组成部分:
- 主体(LV_PART_MAIN)
- 按钮(LV_PART_ITEMS)
知识点1:创建键盘部件
lv_obj_t *kb = lv_keyboard_create(parent);
知识点2:关联文本框
lv_obj_t *ta = lv_textarea_create(lv_scr_act()); /* 创建文本区域部件 */
lv_keyboard_set_textarea(kb, ta); /* 关联键盘和文本区域部件 */
知识点3:设置按键弹窗
lv_keyboard_set_popovers(kb, true); /* 允许按键弹窗提示 */
知识点4:设置键盘模式
lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_NUMBER); /* 数字键盘模式 */
知识点5:获取键盘模式
lv_keyboard_get_mode(kb)
图片按钮
可以将其当作带有图片的按钮。
功能:图片按钮部件类似于按钮部件,不同的是,用户可以在其中设置图片。
图片按钮部件组成部分:主体(LV_PART_MAIN)
知识点1:创建图片按钮部件
lv_obj_t *imgbtn = lv_imgbtn_create(parent);
知识点2:设置图片源、按钮大小
/* 设置某个状态的图片源 */
lv_imgbtn_set_src(imgbtn, LV_IMGBTN_STATE_..., src_left, src_mid, src_right);
/* 设置图片按钮大小 */
lv_obj_set_size(imgbtn, 64 * 3, 64);
知识点3:设置按钮状态
/* 设置按下状态 */
lv_imgbtn_set_state(imgbtn, LV_IMGBTN_STATE_PRESSED);
该函数图片按钮部件专用函数。
选项卡
功能:选项卡部件可以实现多页面切换,用户可以在不同的页面中添加内容。
选项卡部件组成部分
- 主体(lv_obj)
- 按钮(lv_btnmatrix)(一个按钮矩阵)
知识点1:创建选项卡部件
lv_obj_t *tabview = lv_tabview_create(parent, LV_DIR_..., tab_size);
知识点2:添加选项卡
lv_obj_t *tab1 = lv_tabview_add_tab(tabview, "Tab 1");
lv_obj_t *tab2 = lv_tabview_add_tab(tabview, "Tab 2");
知识点3:设置当前选中的选项卡
lv_tabview_set_act(tabview, 1, LV_ANIM_OFF); /* 索引从0开始 */
拓展知识:
获取选项卡的按钮
lv_tabview_get_tab_btns(tabview);
获取选项卡的主体
lv_tabview_get_content(tabview);
例程代码的重点:
LV_PART_ITEMS
LV_STATE_CHECKED
平铺视图
功能:平铺视图部件可以实现不同方向的页面切换,用户可以页面中添加内容。
平铺视图部件组成部分:
- 主体(LV_PART_MAIN)
- 滚动条(LV_PART_SCROLLBAR)
知识点1:创建平铺视图部件
lv_obj_t *tileview = lv_tileview_create( parent );
知识点2:添加页面
定义一个基础对象接收返回值,该返回值可以用作容器,可以在容器里使用开关、按钮、图片等部件。
lv_obj_t *tile1 = lv_tileview_add_tile( tileview, 0, 0, LV_DIR_RIGHT );
lv_obj_t *tile2 = lv_tileview_add_tile( tileview, 1, 0, LV_DIR_LEFT );
知识点3:设置当前显示页面
注意:必须先更新参数
/* 更新参数 */
lv_obj_update_layout( tileview );
/* 根据页面对象设置 */
lv_obj_set_tile( tileview, tile2, LV_ANIM_OFF );
/* 根据页面行列设置 */
lv_obj_set_tile_id( tileview, 1, 0, LV_ANIM_OFF );
移除滚动条
lv_obj_remove_style(tileview, NULL, LV_PART_SCROLLBAR);
窗口
功能:窗口部件可以作为一个容器,展现不同功能的页面。
窗口部件组成部分:
- 头部(Header)
- 主体(Content)
知识点1:创建窗口部件
lv_obj_t *win = lv_win_create(parent, header_height);
知识点2:添加标题、按钮
lv_obj_t *title = lv_win_add_title(win, "Setting");
lv_obj_t *btn = lv_win_add_btn(win, LV_SYMBOL_CLOSE, 20);
解析:
如果是在标题之前添加按钮,那么所添加的按钮就会向左进行对齐;如果是在标题的后面添加按钮,那么所添加的按钮就会向右进行对齐
知识点3:添加主体内容
lv_obj_t *content = lv_win_get_content(win); /* 获取主体 */
lv_obj_t *label = lv_label_create(content); /* 添加内容 */
消息框
消息框部件可以实现弹窗提示,常用于消息通知、确定操作等。
消息框部件组成部分
- 主体(obj)
- 标题(title)
- 关闭按钮(close_btn)
- 内容(content)
- 按钮矩阵(btnmatrix)
知识点1:创建消息框部件
static const char *btns[] = { "Continue", "Close", "" };
lv_obj_t *msgbox = lv_msgbox_create( lv_scr_act(),
"Notice",
"Do you want to continue?",
btns,
true );
知识点2:关闭消息框
lv_msgbox_close(msgbox);
知识点3:获取按钮索引、文本
lv_obj_t *target = lv_event_get_current_target(e); /* 获取当前触发源 */
lv_msgbox_get_active_btn(target); /* 获取按钮索引 */
lv_msgbox_get_active_btn_text(target); /* 获取按钮文本 */
微调器
微调器部件本质上就是一个数字文本,常用于精确调节某个参数的值。
微调器部件组成部分
- 主体(LV_PART_MAIN)
- 光标(LV_PART_CURSOR)
知识点1:创建微调器部件
lv_obj_t *spinbox = lv_spinbox_create(parent);
知识点2:数值递增、递减
lv_spinbox_increment(spinbox); /* 递增 */
lv_spinbox_decrement(spinbox); /* 递减 */
知识点3:设置步进值、范围值
/* 设置步进值,默认为1*/
lv_spinbox_set_step(spinbox, 200);
/* 设置范围值,默认±99999*/
lv_spinbox_set_range(spinbox, -1000, 1000);
知识点4:设置当前值
lv_spinbox_set_value(spinbox, 400);
知识点5:设置数字格式、光标位置
/* 设置数字位数、小数点位置 */
lv_spinbox_set_digit_format(spinbox, 4, 2);
/* 设置光标位置 */
lv_spinbox_set_pos(spinbox, 3);
小数点仅仅用于装饰的作用而且并不会改变当前值。
小数点从左边开始数。
光标的位置从右开始数。
知识点6:获取当前值
/* 返回值为整数,而非小数 */
lv_spinbox_get_value(spinbox);
表格部件
表格部件由一个个单元格组成,它的单元格中只能存放文本形式的内容。
任务调度
不添加延时函数,任务处理的时效性