概念:

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基础对象的框架、思维与概念,以及部分源码解析的更多相关文章

  1. Laravel框架下路由的使用(源码解析)

    本篇文章给大家带来的内容是关于Laravel框架下路由的使用(源码解析),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言 我的解析文章并非深层次多领域的解析攻略.但是参考着开发文 ...

  2. Django框架 之 admin管理工具(源码解析)

    浏览目录 单例模式 admin执行流程 admin源码解析 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在 ...

  3. Django框架rest_framework中APIView的as_view()源码解析、认证、权限、频率控制

    在上篇我们对Django原生View源码进行了局部解析:https://www.cnblogs.com/dongxixi/p/11130976.html 在前后端分离项目中前面我们也提到了各种认证需要 ...

  4. [源码解析] 并行分布式框架 Celery 之架构 (2)

    [源码解析] 并行分布式框架 Celery 之架构 (2) 目录 [源码解析] 并行分布式框架 Celery 之架构 (2) 0x00 摘要 0x01 上文回顾 0x02 worker的思考 2.1 ...

  5. [源码解析] 并行分布式框架 Celery 之架构 (1)

    [源码解析] 并行分布式框架 Celery 之架构 (1) 目录 [源码解析] 并行分布式框架 Celery 之架构 (1) 0x00 摘要 0x01 Celery 简介 1.1 什么是 Celery ...

  6. [源码解析] 深度学习分布式训练框架 horovod (8) --- on spark

    [源码解析] 深度学习分布式训练框架 horovod (8) --- on spark 目录 [源码解析] 深度学习分布式训练框架 horovod (8) --- on spark 0x00 摘要 0 ...

  7. [源码解析] 深度学习分布式训练框架 horovod (18) --- kubeflow tf-operator

    [源码解析] 深度学习分布式训练框架 horovod (18) --- kubeflow tf-operator 目录 [源码解析] 深度学习分布式训练框架 horovod (18) --- kube ...

  8. [源码解析] 深度学习分布式训练框架 horovod (19) --- kubeflow MPI-operator

    [源码解析] 深度学习分布式训练框架 horovod (19) --- kubeflow MPI-operator 目录 [源码解析] 深度学习分布式训练框架 horovod (19) --- kub ...

  9. [源码解析] 深度学习分布式训练框架 horovod (10) --- run on spark

    [源码解析] 深度学习分布式训练框架 horovod (10) --- run on spark 目录 [源码解析] 深度学习分布式训练框架 horovod (10) --- run on spark ...

  10. [源码解析] 深度学习分布式训练框架 horovod (12) --- 弹性训练总体架构

    [源码解析] 深度学习分布式训练框架 horovod (12) --- 弹性训练总体架构 目录 [源码解析] 深度学习分布式训练框架 horovod (12) --- 弹性训练总体架构 0x00 摘要 ...

随机推荐

  1. 降阶公式/ARC173F

    ARC173F 题意 给定 \(n,A,B\),初始有一个集合 \(S=\{1,2,\dots,A,A +1,A+2,\dots,A+B\}\).进行如下操作 \(n-1\) 次使得剩下 \(n\) ...

  2. FLink处理函数ProcessFunction、KeyedProcessFunction、ProcessWindowFunction、 ProcessAllWindowFunction

    一.处理函数简介 在底层,我们可以不定义任何具体的算子(比如 map,filter,或者 window),而只是提炼出一个统一的"处理"(process)操作--它是所有转换算子的 ...

  3. Hetao P1031 萌萌题 题解 [ 蓝 ] [ 线性 dp ]

    萌萌题:一道结合了观察性质的线性 dp. 观察 我们先考虑极端情况:所有数相同,所有数降序排列两种情况. 对于所有数相同的情况,我们发现,最终可以合并出来的区间,最多只有 \(n \log n\) 个 ...

  4. MarkDown学习使用图片

    学习MarkDown使用

  5. CF1837E Play Fixing 题解

    首先来考虑什么情况方案数为 \(0\): 可以确定,在某一层中,两个原本都能晋级的队伍比赛: 可以确定,在某一层中,两个原本都不能晋级的队伍比赛. 发现假如写出每一场比赛及其胜者,可以形成一棵树形结构 ...

  6. 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体的替代品,可本地部署+知识库,注册即可有750w的token使用

    最近火山引擎推出了自家联网版的DeepSeekR1,并且加入了联网的功能,不用担心DeepSeek本体的服务器繁忙了,可以说直接是DeepSeek本体的替代品.现在注册即送30块体验价(相当于750w ...

  7. QT5笔记:10. 容器类的迭代

    1. 这里指的是Java类型的迭代器,即使用方式和Java中一致 代器的使用例子(适用于可读可写迭代器) QList<QString>list;//声明容器类 list << ...

  8. autMan奥特曼机器人-自建autMan插件市场

    一.自建市场配置 配置参数 二.上架设置 设置哪些插件上架,哪些不上架 三.检测是否成功 怎样检查是否成功了?订阅一下自己,然后看应用市场上是否显示 四.用户怎样购买插件 用户想买自建市场作者的插件, ...

  9. Typecho博客服务器搬家换空间方法教程

    Typecho 博客搬家方法步骤: 1.备份Typecho博客数据库,进入到phpmyadmin选择自己博客的数据表进行导出备份 2.使用FTP(或者登陆空间控制面板)把所有的Typecho文件下载到 ...

  10. SSM - 狂神的项目示例

    出于对狂神的崇拜,总结SSM项目. 基本介绍 项目分层 基本介绍 项目名称:ssmbuild 介绍:通过书籍管理系统实现一个简单的SSM项目,可以作为其他Java Web项目的借鉴. 主要功能模块:查 ...