赞
踩
详细的内容可以参考正点原子的LVGL开发指南,本文只记录重点内容
正点原子后续的例程都是基于操作系统来写的
在 LVGL 中,用户界面的基本构建成分是对象,也称为小部件,例如:按钮、标签、图片、列表、图表、文本区域,等等。值得注意的是,LVGL 图形库虽然是由 C 语言开发的,但其所采用的是一种面对对象编程思维,这就涉及到了“类”的概念。
在 C语言中,并没有“类”的概念,而 LVGL通过结构体的形式实现了“类”的功能(并非真的“类”)
也就是说,每一个部件都是一个对象,我们直接针对部件对象来操作即可。
为了方便统一管理,LVGL的所有部件都会有一个父类,LVGL中,父类是属于一种最基础的基础对象。
基础对象本身就是一个小部件,当它被创建出来之后,其呈现出一个矩形。
除此之外,基础对象还是其他小部件的父类,所有部件的位置、大小等基本属性都是归基础对象管理的。屏幕就是最顶层的一个父类(除了屏幕没有自己的父类,其他部件都有)
由上图可知,在 LVGL 中,首先定义了 lv_obj_t 这个结构体,然后通过这个结构体去实例化一个基础对象(lv_obj),这个基础对象将作为父对象,去衍生更多的子对象(其他部件)。
值得注意的是,通过这种“类”的方式去衍生其他部件,所衍生出来的部件将会继承父对象的一些基本属性,例如大小、位置、样式,等等,因此,我们可以通过一套统一的函数去管理不同部件的基本属性。
基础对象的作用有四个:
① 管理其他部件的基本属性;
② 作为背景装饰;
③ 辅助布局;
④ 界面切换。
第一个作用内容比较多,我们后面单独讨论,先说下其他三个作用
1. 作为背景装饰
当基础对象被创建出来后,它默认是一个圆角矩形,如下图所示:
在设计较为复杂的 GUI 界面时,不同功能的模块之间需要清晰地划分区域,此时,我们
可以使用基础对象作为背景,对不同的区域进行划分。
2. 辅助布局
当 GUI 界面中有一些组成内容相似的模块时,可以利用基础对象作为父对象,创建出其他的部件,这些部件将出现在基础对象内部,此时,我们只需要管理各基础对象之间的布局即可,其他的部件会随之变化。类似于编组。
3. 界面切换
当基础对象做为父对象,创建出其他的部件时,这些被创建出来的部件将出现在其父对象的内部,换言之,此时的基础对象就是一个容器,它里面子对象会随之移动。在 UI 设计中,我们可以利用上述的特性,实现界面的切换,示意图如下所示:
由上图可知,基础对象 1、2 分别用于管理界面 1、2,它们之中存在一些子对象(例如开关),当用户需要切换界面时,只需切换容器即可。
LVGL 官方提供了很多与基础对象相关 API 函数,如下表所示:
最常用的有两个
创建基础对象
这里的创建函数为lv_obj_create
传入一个父对象,返回一个基础对象。
注意,LVGL里的对象类型都是lv_obj_t,但是有不同的创建函数
获取对象状态
上面说了,屏幕是属于最顶层的一个父类,也就是一个基础对象。
示例如下:
除了基础对象,其他部件也属于一个一个的对象,在学习其他部件之前,我们先借着基础对象来了解下,这些部件对象都有哪些基本的性质。
对象的基本属性
在 LVGL 中,每个对象都有一些相同的基本属性,例如:
① 父类
② 大小
③ 位置
④ 样式
⑤ 事件
这些属性都是通用的,所有对象都有,所以设置函数只针对属性,而具体的对象是通过参数传递进入的。
对象的私有属性
在对象衍生的过程中,不同的对象(部件)会拥有一些特殊的属性,也称为私有属性。
注意私有属性设置函数命名和通用属性设置函数命名的区别,通用属性设置函数的第二个字母为obj,而私有属性设置函数的第二个字母就是对应的部件名
父对象与子对象的关系
父对象(下文称为父类)可以视为子对象(下文称为子类)的容器,当子类被创建出来之 后,它是在父类里面的。注意:一个父类可以拥有多个子类,而子类就只有一个父类(屏幕除外)。
接下来,我们介绍父类和子类之间的关系:
1
父类移动,则子类也会随着父类移动,如下图所示:
2
子类移动,父类并不会随之移动,如果子类移动的位置超出父类的范围,则超过的部分默认不可见,如下图所示:
上图中,子类的黄色部分超出了父类的范围,这个部分将默认不可见。
3
子类在设置坐标位置时,坐标原点在父类的左上角,示意图如下所示:
在上图的例子中,父类设置位置时,是以整个显示屏的坐标原点(0,0)为参考点的,而对于子类来说,其设置位置时,则是以父类的左上角坐标点为参考点,如上图中的点A(400,240)。
在 LVGL 中,用户可以在程序运行时动态创建或者删除一个对象。当对象被创建时,将消耗一定的内存,而当其被删除时,这部分内存将得到释放。
注意,基础对象创建时中间的关键词是obj
创建对象的函数只是有统一的格式,而这些删除对象的函数是通用的。
我们介绍界面切换的两种实现方法:
方法一:删除法
当用户删除一个父对象时,它所有的子对象也会被一并删除,因此,我们需要实现界面的切换,可以调用 lv_obj_del 函数,直接删除基础对象(父对象),然后再创建新的界面,这样即可实现界面切换,示意图如下所示:
方法二:隐蔽法
此方法的原理和删除法类似,只不过这里是将界面隐藏起来,需要的时候还能还原。
注意:
隐藏的界面并未被删除,其占用内存也没有得到释放,因此,当用户使用此方法切换界面时,需要考虑内存溢出的隐患。隐蔽法的示意图如下所示:
由上图可知,隐藏法的实现逻辑如下:先创建出不同的界面,然后调用 lv_obj_add_flag 函
数,为指定的界面添加隐藏的标志,此时,该界面将隐藏,而当我们需要显示某个界面时,只需要调用 lv_obj_clear_flag 函数,清除隐藏属性即可。注意:不要同时清除多个界面的隐藏属性,否则可能出现显示混乱的问题。
两种方法各有什么利弊呢?后续再补充。
关于 LVGL 的图层,大家只需要搞清楚 3 个问题即可:
① 当用户创建两个对象,而这两个对象的区域出现重叠时,重叠的部分将如何绘制?
② 两个对象出现重叠,怎样把底下的对象移到上层?
③ LVGL 的图层有哪些?
接下来,我们围绕着这三个问题来讲解 LVGL 图层的知识。
活动屏幕层就是我们常规使用的那一层,顶层一般是用于弹窗,系统层一般是用于鼠标显示。
LVGL 的布局设计深受 CSS 启发,其主要内容涉及 3 个方面:坐标位置、大小以及对齐方式
对齐部分表格太长,所以直接参考正点原子开发指南的这一部分即可。
对齐分为内部对齐和外部对齐,内部对齐是子类和父类之间的对齐;外部对齐是各父类整体之间的对齐。
在 LVGL 中,常用于设置对齐方式的函数有 3 个:
样式即对象的外观,而 LVGL 的样式设置深受 CSS 的启发,其特点如下:
LVGL 样式设置方法
在 LVGL 中,设置样式属性的方法有两个:
普通样式适合批量应用,本地样式针对性强。
注意二者在设置函数命名上的差异,本地样式相对普通样式,多了个obj,说明它是针对具体对象的,而上面是普遍使用的。
在lvgl中,各种部件都是由不同的部分组成的,举个例子,当我们绘制一个圆角矩阵时,可将其分解为两个部分,例如直线部分和圆弧部分,这样即可组成为圆角矩阵,如下图所示:
在 LVGL中,也利用了上述的原理,将一个复杂的部件分解成多个组成部分,这样我们即可单独地设置某个组成部分的样式。注意:如果用户想设置某个组成部分的样式,则需要在设置样式时选择该组成部分的对应枚举。各个组成部分对应的枚举如下表所示:
注意,这里是全部列出来了,实际上,不同的部件有着不同的组成部分。
接下来,我们结合上表,以进度条部件(Slider)为例,分析它的组成部分,如下图所示:
在 LVGL 中,所有的部件状态如下表所示:
上表中,部件状态相关的枚举较少且不难理解,我们一般在两种情况下会用到状态枚举:
上面说了样式的设置,那么,具体有哪些样式可以进行设置呢?
涉及的样式比较多,这里就不一一列出来了,可自行参考开发指南6.4.4 LVGL 样式属性
其实LVGL的绘制无非就是创建部件对象,然后设置对应的属性。
注意:16位的颜色深度不支持Alpha通道的透明属性设置。
LVGL 的字体功能是较为强大的:支持 UTF-8 编码、图标字体、自定义字体、最高 8bpp的抗锯齿,等等。值得注意的是,bpp 值越大,字体的边缘会越平滑,但其对内存的占用就越多,在界面上进行字体渲染时,绘制速度也会越慢,一般的项目,采用 4bpp 就足够了。
启用 UTF-8 编码
LVGL 支持 2 种编码方式:第一种是 ASCII 编码,这种编码只支持英文字符的显示;第二种是 UTF-8 编码,这种编码可以支持全球所有字符的显示。用户需要在 LVGL 工程中启用UTF-8 编码,可以打开 lv_conf.h 文件,修改 LV_TXT_ENC 配置项,如下源码所示:
默认就是UTF-8编码。
这里建议大家将 MDK 软件设置为 Chinese GB2312 编码,以更好地兼容中文。
使用 LVGL 内置图标字体
图标字体是 web 前端中流行的一种技术,它以字体的形式,呈现出一个单色的图标。在 LVGL 中,自带了许多常用图标字体,这极大地方便了用户的界面开发。大家需要使用这些图标字体,可以打开lv_symbol_def.h文件,查找相应的图标字体枚举。
当用户调用上述的图标字体枚举,它们将显示成图标。
使用 LVGL 内部字库
LVGL 提供了一套内置的字库,这些字库在移植的时候已经被添加到工程当中,我们打开
Middlewares/lvgl/src/font 分组,即可找到这些字库文件,如下图所示:
接下来,我们介绍 LVGL 内部字库的使用流程:
1. 使能字库
打开 lv_conf.h 文件,将所需要使用的内部字库使能(宏定义置 1)
2.调用字库
使用自定义字库
另外,还有自定义字库的使用,具体可参考开发手册8.4 使用自定义字库
参考这篇:LVGL库入门教程 - 颜色和图像 - 冰封残烛 - 博客园 (cnblogs.com)
以下仅记录颜色相关的内容
在 LVGL 中,颜色以结构
lv_color_t
表示。在最开始移植整个工程时,曾经在lv_conf.h
中修改过颜色深度。LVGL 会自动根据所选的颜色深度创建合适的颜色结构。当我们要表示某种颜色时,就传入lv_color_t类型的颜色数据。
可是有个问题,我们并不知道lv_color_t类型的颜色数据是怎么样的。
我们日常使用的颜色信息最直观的就是就是红橙黄绿青蓝紫,或者再深入点就是24位RGB色号,怎么能通过这些直观的颜色信息得到lv_color_t类型的像素数据呢?
主要有以下两种方式:
1
lv_color_hex函数
比如:
lv_color_t aqua = lv_color_hex(0x00FFFF); // 从十六进制创建
传入24位色号,创建过程中会自动转换为合适的颜色值。
2
lv_palette_main函数
如果觉得 16 进制的颜色还是不够直观,还可以使用调色板功能。LVGL 提供了常用颜色的色值表示,可以直接使用、微调、混合这些颜色。
例如,以下直接调出了一个紫色:
lv_color_t purple = lv_palette_main(LV_PALETTE_PURPLE);
GUI Guider是恩智浦为LVGL开发了一个上位机GUI设计工具,可以通过拖放控件的图形化设计方式开发LVGL GUI页面,加速GUI的设计。
相比LVGL官方推出的付费工具 SquareLine Studio ,GUI Guider完全免费,它们甚至开发页面的布局都类似,但两者功能上,GUI Guider也相应的没有SquareLine Studio 细致和丰富,希望NXP能持续的优化更新
GUI Guider工具完成的GUI设计可在PC端仿真运行,实现无硬件开发,通过仿真调试完成后,可快速方便的整合到MCU的工程中。
更多参考:
【LVGL】GUI神器 NXP GUI GUIDER开发工具入门教程-CSDN博客
ESP32系列之LVGL(三):Gui-Guider的使用_gui guider-CSDN博客
UI初版可借助GUI工具生成,然后移植过来使用,不过首次接触时,建议手撸界面。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。