LVGL基础对象的框架、思维与概念,以及部分源码解析
概念:
Lvgl虽然是以C语言进行编程开发,但其中借鉴了CSS当中编程思想,引入了类与对象的概念,其中lvgl的基础单位为控件,等同于HTML5当中的标签。
Lvgl当中的“类”是以结构体来进行实现的,以8.3版本为例(以下源码均为8.3):

通过lv_obj_t* obj =lv_xxx_create(parent)的形式进行实例化对象,lv_obj_t结构体来进行设置与保存控件的所有属性与样式,源码如下:

又以基础对象为基础模板,通过“类”的结构体衍生出其他控件,使得控件多样化,如:滑块、弧、按钮、键盘等。
这种操作有些类似于JS当中的构造函数,介于此,我们也就可以通过LVGL当中的内置函数来进行区分不同类型的控件了,lv_obj_check_type(obj, &lv_btn_class),该函数参数一为要检测的控件,参数二则是对应的类型,内部源码实现非常简单,仍然是使用的是lv_obj_t来进行储存相关信息,这都是典型的类与对象思维,源码如下:


结构:
lvgl对象结构依然与css结构相同,是以家庭结构来进行整体控制(也可以理解为套娃),最外层是整个屏幕,也可以理解为所有控件的祖先,当创建控件时,是以父子结构来进行创建,如果我们想在屏幕上创建一个按钮,则可以lv_btn_create(屏幕)。
其中屏幕则是按钮的“父亲”,按钮与屏幕之间则为父子关系,如果我们又在按钮当中创建一段文字来表示按钮功能,则可以lv_label_create(按钮)。
其中关系为,屏幕是按钮的父亲,按钮是文字的父亲,屏幕则是文字的祖父,依赖于这种家庭制的关系,我们可以随时找到任意一个家庭成员,在lv_obj_t的结构体中保存了其父亲与子辈,注意:控件只有一个父亲,但可以有无数个儿子。

当然我们不可能去手动调动结构体来进行获取子控件或者父控件,那太不符合一个成熟的框架架构,LVGL提供了内置函数来进行获取其父控件与子控件,lv_obj_get_child(parent, id)与lv_obj_get_parent(Obj),其中lv_obj_get_child来进行获得子控件,参数分别是父控件与子控件的索引,这个索引通常是子控件创建的顺序(从0开始),lv_obj_get_parent则是用来获取控件的父控件。我们也可以通过源码来查看,他具体是怎么处理父子控件的,如果我们学过数据结构,则很容易看的懂其源码,在lv_obj_create中lv_obj_class_create_obj函数中有段源码如下:

但有时候,我们可能将某个或者多个子控件删除了,或者进行了其他操作,导致索引值不在等于创建顺序了,而且恰好子控件都是局部变量,那我们应该如何获取我们想要的子控件呢?
我们可以使用lv_obj_check_type,但这并不准确,如果我们创建很多个文本,我们很难用lv_obj_check_type来辨别出谁是我们想要的子控件。这时我们可能用的lvgl提供的另一个内置函数,lv_obj_set_user_data,这个函数可以将一个void*的数值绑定在控件时,当我获取到拿到子控件后,再通过lv_obj_get_user_data将其获取出来,然后再进行比对。
这个数据仍然是绑定在lv_obj_t的结构体当中,我们可以点开源码,看到他具体的位置与实现方式:


以上操作我们可能需要遍历所有子控件,那我们该如何获取子控件的数量呢?直接结构体调出来?通过结构体获取太长了导致不太好看,也就是可读性差,lvgl提供了封装好的函数接口,lv_obj_get_child_cnt,虽然也是调用结构体,但好看多了,源码如下:

有时候我们可能需要刷新列表内容,这时候可能需要清除所有内容,重新创建,有没有类似功能的函数接口,有的,lv_obj_clean(obj),调用该函数则会清空所有子控件。
至于内部如何实现的删除某个控件的,则是先遍历其所有子控件,递归删掉所有后代控件,判断是否在屏幕上显示,如果显示了则通知屏幕刷新,然后在其父控件的children中将其删除,感兴趣的可以去看源码。
言归正传这种家庭制与现实中的家庭及其相像,在现实中儿子一般都会遗传父母的长相,在LVGL中子控件则可以遗传父控件部分样式,称之为继承,就如同现实中,父亲长得很帅,儿子一般长得也不差。当然这并不意味着所有的外貌都可以遗传,比如父亲很胖,儿子却不一定很胖,在LVGL当中同样如此,子控件只能继承父控件的部分样式,以下为可以继承的样式:
1.文本相关属性
子控件若未显式设置以下属性,会直接继承父控件的值:
字体(text_font)
文本颜色(text_color)
文本透明度(text_opa)
文本对齐方式(text_align)
文本装饰(如下划线、删除线等)
示例:若父控件设置 lv_style_set_text_color(&parent_style, LV_COLOR_RED),子控件的文本默认也会显示为红色。
2.部分视觉属性
背景透明度(bg_opa)
部分渐变色属性(若父控件定义了全局渐变规则)
阴影颜色(shadow_color,但需父控件未覆盖子控件的显式设置)
注:这些属性的继承需符合特定条件,例如子控件未单独定义相关属性。
3.状态关联的样式
若父控件为特定状态(如 LV_STATE_PRESSED)定义了样式,子控件在相同状态下可能继承该状态的属性,除非子控件单独设置。
儿子除了可以继承父母的带来的便利以外,也会受到父母的影响,在LVGL中亦是如此,如果我们将父控件删除lv_obj_del(父亲),那么当父控件删除的那一刻,子控件也随之被删除。
在古代,我们有一种关系叫做过继,尤其是亲兄弟之间,如果有一方因为种种原因后继无人,无人继承家业,这时候如果亲兄弟有几个孩子,则可以过继一个来继承家业,lvgl也有同样的操作,lv_obj_set_parent该函数可以将控件换个父亲。
除了父子关系,还有兄弟关系,兄弟之间关联相较于父子关系则没有那么明显,主要是通过父亲来进行联系,但是兄弟之间也是有互相影响的,小儿子与小女儿往往会更受到父亲的喜爱,在LVGL中同样如此,如果两个控件共有一个父控件,并且位置重合的情况下,则会显示新建立的控件,情况如下图:

显示在其他控件上面的情况我们称之为前景,显示在下面的情况称之为背景。
但很多时候我们并不希望这种情况的发生,lvgl提供了相应的函数接口来控制谁显示在上面,谁显示在下面,当发生类似的情况时,我们调用这接口来进行控制。
使用lv_obj_move_foreground(obj) 显式地告诉库将对象带到前景。类似地,使用 lv_obj_move_background(obj) 将对象 obj 移动到背景。
也可以使用lv_obj_set_parent(obj,new_parent) , 将obj显示在 new_parent 的前面。
世子之争向来激烈,有时候老二不想当老二了,想当老大,有没有类似的操作,有的,lv_obj_move_to_index(obj,index),该函数主要作用是将控件移到指定索引,可能会问,谁在前谁在后,又不分家产,我还可以设置前景与后景,这有何用?有的!在布局当中会有大用。
而且前景与背景的设置也是调用的该函数,源码如下:


LVGL基础对象的框架、思维与概念,以及部分源码解析的更多相关文章
- Laravel框架下路由的使用(源码解析)
本篇文章给大家带来的内容是关于Laravel框架下路由的使用(源码解析),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言 我的解析文章并非深层次多领域的解析攻略.但是参考着开发文 ...
- Django框架 之 admin管理工具(源码解析)
浏览目录 单例模式 admin执行流程 admin源码解析 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在 ...
- Django框架rest_framework中APIView的as_view()源码解析、认证、权限、频率控制
在上篇我们对Django原生View源码进行了局部解析:https://www.cnblogs.com/dongxixi/p/11130976.html 在前后端分离项目中前面我们也提到了各种认证需要 ...
- [源码解析] 并行分布式框架 Celery 之架构 (2)
[源码解析] 并行分布式框架 Celery 之架构 (2) 目录 [源码解析] 并行分布式框架 Celery 之架构 (2) 0x00 摘要 0x01 上文回顾 0x02 worker的思考 2.1 ...
- [源码解析] 并行分布式框架 Celery 之架构 (1)
[源码解析] 并行分布式框架 Celery 之架构 (1) 目录 [源码解析] 并行分布式框架 Celery 之架构 (1) 0x00 摘要 0x01 Celery 简介 1.1 什么是 Celery ...
- [源码解析] 深度学习分布式训练框架 horovod (8) --- on spark
[源码解析] 深度学习分布式训练框架 horovod (8) --- on spark 目录 [源码解析] 深度学习分布式训练框架 horovod (8) --- on spark 0x00 摘要 0 ...
- [源码解析] 深度学习分布式训练框架 horovod (18) --- kubeflow tf-operator
[源码解析] 深度学习分布式训练框架 horovod (18) --- kubeflow tf-operator 目录 [源码解析] 深度学习分布式训练框架 horovod (18) --- kube ...
- [源码解析] 深度学习分布式训练框架 horovod (19) --- kubeflow MPI-operator
[源码解析] 深度学习分布式训练框架 horovod (19) --- kubeflow MPI-operator 目录 [源码解析] 深度学习分布式训练框架 horovod (19) --- kub ...
- [源码解析] 深度学习分布式训练框架 horovod (10) --- run on spark
[源码解析] 深度学习分布式训练框架 horovod (10) --- run on spark 目录 [源码解析] 深度学习分布式训练框架 horovod (10) --- run on spark ...
- [源码解析] 深度学习分布式训练框架 horovod (12) --- 弹性训练总体架构
[源码解析] 深度学习分布式训练框架 horovod (12) --- 弹性训练总体架构 目录 [源码解析] 深度学习分布式训练框架 horovod (12) --- 弹性训练总体架构 0x00 摘要 ...
随机推荐
- 「SPOJ2666」QTREE4 - Query on a tree IV
题目概述 对一棵树维护两种操作:翻转某个点的颜色,求 \(max\{ dist_{u, v} \}\) 且满足 \(u\) 的颜色和 \(v\) 的颜色都是白色( \(u,v\) 可以相同). 思路 ...
- [ARC 188A] ABC Symmetry
solution by XiangXunYi 思路推导 step 1 首先题目中操作二同时删掉 A,B,C 的条件相当于同时将三者数量减一,操作一删掉两个相同字符等同于将某一字符的数量减二,那么我们可 ...
- uni-app如何只用插件市场中的插件
将你需要的插件下载下来.比如说如下图 在pages.json配置 globalStyle是一个单独的字段 "globalStyle": { "usingComponent ...
- redis 过期监听配置
package org.jeecg.config; import java.lang.reflect.Method; import java.time.Duration; import java.ut ...
- Visual Studio各个版本密钥
1.VS2012 旗舰版:YKCW6-BPFPF-BT8C9-7DCTH-QXGWC 2.VS2013 旗舰版:BWG7X-J98B3-W34RT-33B3R-JVYW9 专业版:XDM3T-W3T3 ...
- oracle之sqlplus删除键不能用
方法一 1.终端命令,临时有效,重连失效 stty erase ^H 2.配置环境变量,永久有效 vi -oracle/.bash_profile stty erase ^H source -orac ...
- lvm相关命令及/etc/fstab开机挂载
名词解释: PV: 物理卷(physicalvolume)物理卷就是指硬盘分区或从逻辑上与磁盘分区具有同样功能的设备(如RAID),是LVM的基本存储逻辑块,但和基本的物理存储介质(如分区.磁盘等)比 ...
- 记录一次WPF程序进程挂起问题
## 1. 使用背景 开发`WPF`单进程项目,在项目中使用`MongoDB`数据库,需要连接多个不同的数据库实例,另外项目框架采用了事件聚合器来管理模块间的通知调用,基于`NetMQ`实现了一个`Z ...
- C# 性能优化 --- Lazy<T> 用法学习
参考原文:https://kb.cnblogs.com/page/99182/ 延迟实例化,对于需要创建大量对象,而又不需要立即使用的场景非常有用.一下实例说明了Lazy<T>的用法. u ...
- Python if分支
分支语句: 1.单分支语句 1 if 条件表达式: 2 print("如果成立怎么养怎么样") 例:让用户输入年龄,如果大于18就可以去网吧偷耳机age = int(input(& ...