前言
LVGL(LittlevGL)是一个开源的嵌入式图形库,用于在嵌入式系统中创建用户界面。LVGL提供了一系列丰富而灵活的功能,使得开发者能够轻松创建漂亮、交互性强的用户界面。其中,lv_obj是LVGL中的基础对象,为整个图形库的构建提供了坚实的基础。
本文将深入探讨LVGL的基础对象lv_obj,解释其在嵌入式界面开发中的关键作用。我们将介绍lv_obj的基本概念、用法和一些常见的应用场景,以帮助开发者更好地理解和利用LVGL进行嵌入式图形界面开发。
一、LVGL9的下载
这里我们使用百问网提供的CodeBlocks提供给我们的lvgl模拟器
百问网团队已经将LVGL windows模拟器(CodeBlocks)已更新到V9.0.0版本,支持更多特性!
视频效果: 视频效果
项目获取地址: 获取地址
对于LVGL9的文档:文档地址里面为英文文档
二、基础对象lv_obj
2.1 概述
基础要素定义:'基础对象’的属性
坐标: 定义屏幕上的位置,这些坐标决定了小部件的显示位置。
父对象: 建立了一个层次结构,父对象表示对象树中的直接上级。
子对象: 采用嵌套结构,'基础对象’可以包含其他对象作为其子对象,形成有序的组织结构。
样式: 在美学领域发挥着关键作用,'基础对象’包含了这些样式,允许开发人员定制小部件的外观。
属性,如 Clickable、Scrollable 等。
面向对象范式中的继承
在面向对象编程的精神中,“基础对象”扮演了基类的角色。LVGL中的所有其他对象都继承自这个基础类,从而实现了一种系统化和一致的对象设计方法。
灵活多变的功能:超越基础功能
“基础对象”的力量不仅仅限于其基本属性。其函数和功能不仅仅局限于自身;它们可以与其他小部件一起使用。一个具体的例子是使用lv_obj_set_width(slider, 100),展示了“基础对象”的方法的多功能性。
独立简洁:基础对象作为小部件
有趣的是,“基础对象”不仅仅是幕后的设计师,还可以独立成为一个小部件。在其最简单的形式中,它表现为一个矩形。类比HTML,将其想象成一个<div>——在Web开发中的基本容器。
总体而言,“基础对象”是LVGL的关键组成部分,指挥着屏幕上小部件的交响曲。它提供了一个统一的基础,确保设计界面的一致性、多功能性,并能够创建复杂的图形界面。无论是作为继承的基石还是作为小部件的焦点,基础对象都体现了LVGL设计哲学中简单和强大的本质。
2.2 布局
Similarly to many other parts of LVGL, the concept of setting the coordinates was inspired by CSS.
LVGL has by no means a complete implementation of CSS but a comparable subset is implemented (sometimes with minor adjustments).
在官网可以看到这些,这表示:与LVGL的许多其他部分类似,设置坐标的概念受到了CSS的启发。LVGL并没有完全实现CSS,但实现了一个可比较的子集(有时进行了轻微的调整)。这意味着LVGL借鉴了CSS的思想来设置对象的坐标,但并非完全按照CSS的规范实现,而是实现了一个相似的子集,有时进行了一些小的调整。
明确定义的坐标信息被存储在样式中(包括大小、位置、布局等)。
支持设置最小宽度、最大宽度、最小高度和最大高度。
支持像素、百分比和“content”单位。
对于上面这个单位:
像素(pixel):简单地说,就是以像素为单位的位置。整数始终表示像素。例如,lv_obj_set_x(btn, 10)
表示将按钮的横坐标设置为10个像素。
百分比(percentage):表示对象大小相对于其父对象或父容器的百分比(取决于具体属性)。lv_pct(value)
将一个值转换为百分比。例如,lv_obj_set_width(btn, lv_pct(50))
表示将按钮的宽度设置为父容器宽度的50%。
LV_SIZE_CONTENT:这是一个特殊的值,用于将对象的宽度/高度设置为包含所有子元素的尺寸。类似于CSS中的概念。例如,lv_obj_set_width(btn, LV_SIZE_CONTENT)
.auto 表示将按钮的宽度调整为包含所有子元素,并自动适应内容的大小。
简单来说:这意味着 LV_SIZE_CONTENT 会根据子元素的大小自动调整父元素的尺寸,确保容纳所有内容。就像在 CSS 中使用 auto 可以让元素自动适应其内容一样,使用 LV_SIZE_CONTENT 也能够让 LVGL 的对象自动调整大小,以包含其内部的所有子元素。
当x=0,y=0时,坐标表示相对于父元素的左上角,加上左/上内边距和边框宽度。
宽度/高度表示整体尺寸,而“content area”(内容区域)会考虑内边距和边框宽度,因此实际内容区域较小。
提供对Flexbox和Grid布局的支持,但仅实现了它们的子集功能。
2.3 lv_obj的使用
创建一个lv_obj
首先我们需要知道一个类型:lv_obj_t
,如果我们想创建之后拿到这个部件我们就需要使用这个类型来存储
创建lv_obj形式:
lv_obj_t *obj = lv_obj_create(parent);
参数类型为lv_obj_t *
其中parent为你需要设置的父类,换句话说,它决定了新创建的对象在界面上的层级关系和位置。如果把界面比作一个家庭,parent就像是新对象的父母,它确定了新对象在家庭中的位置和归属关系。在程序中,这意味着新对象将会被添加到parent对象的子元素列表中,并且它的位置和大小可能会受到parent对象的影响。
其中,在lvgl中最顶级的父类可以这样创建lv_scr_act()
,他会返回一个lv_obj_t *
可以看到,左上角就是我们创建的类似于div的东西了
设置大小
我们可以使用
lv_obj_set_width(obj, new_width)
lv_obj_set_height(obj, new_height)
lv_obj_set_size(obj, new_width, new_height).
他们的作用分别是:设置obj的宽度,高度或者高度和宽度一起设置
示例代码:
lv_obj_t *obj1 = lv_obj_create(lv_scr_act());
lv_obj_set_size(obj1,500,500);
我们还可以使用lv_pct函数设置相对于父类的百分比大小
lv_obj_t *obj1 = lv_obj_create(lv_scr_act());
lv_obj_set_size(obj1,lv_pct(50),lv_pct(50));
这样就刚好一半了,我们改变窗口大小,他也会一起改变
设置位置
我们可以使用下面三个函数来设置obj的位置
lv_obj_set_x(obj, new_x)
lv_obj_set_y(obj, new_y)
lv_obj_set_pos(obj, new_x, new_y)
他们分别是设置obj的x位置、y位置和x,y一起设置
示例代码:
lv_obj_t *obj1 = lv_obj_create(lv_scr_act());
lv_obj_set_size(obj1,lv_pct(50),lv_pct(50));
lv_obj_set_pos(obj1,220,200);
需要知道的是,只要是可以填单位的地方,百分比和像素都可以填,如果不是百分比/LV_SIZE_CONTENTD都是像素为单位
设置对齐
LVGL提供函数可以让一个obj相对于父类进行对齐
设置形式:
lv_obj_set_align(obj, LV_ALIGN_...)
示例代码:
lv_obj_t *obj1 = lv_obj_create(lv_scr_act());
lv_obj_set_align(obj1,LV_ALIGN_CENTER);
我们除了对齐父对象,我们还可以指定对齐的对象
lv_obj_align_to(obj_to_align, obj_reference, LV_ALIGN_..., x, y)
其中x,y是对齐后偏移的数量,比如x轴,如果是10,则对齐后向右偏移10,y轴也是一样的
对齐的一些宏:
父对象与子对象
lv_obj_set_parent(obj, new_parent)
lv_obj_get_parent(obj)
我们可以通过上面来设置/获取某个对象的父类
我们可以使用:
lv_obj_get_child(parent, idx)
获取某个对象的指定下标的子类,参数2为下标,从0开始
lv_obj_get_child_count(parent)
我们可以使用上面这个函数来获取某个obj父类的子类个数
比如可以这样操作:
uint32_t i;
for(i = 0; i < lv_obj_get_child_count(parent); i++) {
lv_obj_t * child = lv_obj_get_child(parent, i);
/*Do something with child*/
}
除了上面这些函数,还有一些其他的对于我们操作的函数:
lv_obj_get_index(obj):这个函数返回一个对象在其父对象中的索引。它等同于父对象中比该对象年轻的子对象的数量。例如,如果一个对象是父对象的第一个子对象,那么它的索引为0。
下面三个函数会改变他们在界面上的显示效果
lv_obj_move_foreground(obj) 和 lv_obj_move_background(obj):这两个函数用于将对象置于前景或背景。通过调用 lv_obj_move_foreground(obj),你可以将指定对象移到其父对象的子对象列表的最前面,使其显示在其他对象的上方。相反,lv_obj_move_background(obj) 将对象移到列表的最后,使其显示在其他对象的下方。
lv_obj_move_to_index(obj, index):这个函数用于改变对象在其父对象中的索引,从而改变其在层次结构中的显示顺序。通过指定新的索引,你可以将对象移动到父对象的子对象列表的特定位置。
lv_obj_swap(obj1, obj2):这个函数用于交换两个对象在其父对象中的位置。调用此函数将 obj1 和 obj2 在父对象的子对象列表中的位置互换,从而改变它们在层次结构中的显示顺序。
事件
事件就是触发了一个事情然后去执行一个函数
为一个obj添加一个事件:
void lv_obj_add_event_cb(lv_obj_t *obj, lv_event_cb_t event_cb, lv_event_code_t filter, void *user_data)
参数1为你要设置事件的对象,参数3为事件的类型比如点击LV_EVENT_CLICKED
参数2为回调函数,参数4为要传递的信息(如果没有可以传NULL)
其中回调函数这样写:
static void my_event_cb(lv_event_t * event)
{
printf("Clicked\n");
}
示例代码:
#include <stdlib.h>
#include <unistd.h>
#include "lvgl/lvgl.h"
void callback(lv_event_t *e)
{
printf("clicked\n");
}
void LV_OBJ()
{
lv_obj_t *obj1 = lv_obj_create(lv_scr_act());
lv_obj_add_event_cb(obj1,callback,LV_EVENT_CLICKED,NULL);
}
总结
在LVGL中,lv_obj作为基础对象扮演着关键的角色。通过lv_obj,开发者可以创建、管理和控制各种图形元素,如窗口、按钮、标签等。lv_obj提供了丰富的功能和方法,使得开发者能够轻松实现各种复杂的用户界面。
本文介绍了lv_obj的基本概念,重点阐述了其在LVGL图形库中的作用和用法。通过深入理解lv_obj,开发者可以更加高效地利用LVGL进行嵌入式图形界面的设计与开发。希望本文能够为LVGL初学者提供一个良好的入门指南,使他们能够更加轻松地掌握LVGL图形库的核心概念和使用方法。