LVGL Basics(LVGL 基础)

显示原文

LVGL (Light and Versatile Graphics Library) is a free and open-source graphics library providing everything you need to create an embedded GUI with easy-to-use graphical elements, beautiful visual effects, and a low memory footprint.

How does it do this?


LVGL(轻量且通用的图形库)是一个免费的开源图形库,它提供了创建嵌入式图形用户界面(GUI)所需的一切,包含易于使用的图形元素、出色的视觉效果,并且占用内存少。

它是如何做到这些的呢?

Overview of LVGL's Data Flow(LVGL 数据流概述)

显示原文
LVGL Data Flow

Overview of LVGL Data Flow

You create one Display (lv_display) for each physical display panel, create basics_screen_widgets on them, add basics_widgets onto those Screens. To handle touch, mouse, keypad, etc., you create an Input Device for each. The tick_interface tells LVGL what time is it. Timer Handler(定时器处理程序) drives LVGL's timers which, in turn, perform all of LVGL's time-related tasks:

  • periodically refreshes displays,

  • reads input devices,

  • fires events,

  • runs any animations, and

  • runs user-created timers.


您为每个物理显示面板创建一个 Display (lv_display),在它们上面创建 basics_screen_widgets,再将 basics_widgets 添加到这些屏幕上。为了处理触摸、鼠标、键盘等输入,您要为每种输入 create an Input Devicetick_interface 会告知 LVGL 当前时间。Timer Handler(定时器处理程序) 驱动 LVGL 的定时器,这些定时器进而执行 LVGL 所有与时间相关的任务:

  • 定期刷新显示内容;

  • 读取输入设备;

  • 触发事件;

  • 运行动画;

  • 运行用户创建的定时器。

Application's Job(应用程序的任务)

显示原文

After initialization, the application's job is merely to create Widget Trees when they are needed, manage events those Widgets generate (by way of user interaction and other things), and delete them when they are no longer needed. LVGL takes care of the rest.


初始化之后,应用程序的任务仅仅是在需要时创建部件树,管理这些部件因用户交互及其他情况而生成的事件,并在不再需要时删除它们。其余的工作则由 LVGL 负责。 .. _basics_major_concepts:

Major Concepts(主要概念)

Display vs Screen(显示(Display)与屏幕(Screen))

显示原文

Before we get into any details about Widgets, let us first clarify the difference between two terms that you will hereafter see frequently:

  • A Display or Display Panel is the physical hardware displaying the pixels.

  • A Display (lv_display) object is an object in RAM that represents a Display meant to be used by LVGL.

  • A Screen is the "root" Widget in the Widget Trees mentioned above, and are "attached to" a particular Display (lv_display).


在深入探讨部件的任何细节之前,让我们首先厘清两个你之后会频繁看到的术语之间的区别:

  • 显示设备显示面板 是用于显示像素的物理硬件。

  • 一个 Display (lv_display) 对象是内存中的一个对象,它代表一个供 LVGL 使用的 显示设备

  • 屏幕 是上述部件树中的 “根” 部件,并且 “依附于” 特定的 Display (lv_display) 对象。

Default Display(默认显示设备)

显示原文

When the first Display (lv_display) object is created, it becomes the Default Display. Many functions related to Screen Widgets use the default display. See default_display for more information.


当第一个 Display (lv_display) 对象被创建时,它成为默认显示器。 许多与屏幕小部件相关的功能使用默认显示器。 有关更多信息,请参见 default_display。 .. _basics_screen_widgets:

Screen Widgets(屏幕部件)

显示原文

In this documentation, the term "Screen Widget" is frequently shortened to just "Screen". But it is important to understand that a "Screen" is simply any Widget created without a parent --- the "root" of each Widget Tree.

See Screens for more details. .. raw:: html

</details> <br>

在本文档中,“屏幕小部件”一词经常缩写为“屏幕”。但重要的是要理解,“屏幕”只是任何没有父级的 小部件 —— 每个小部件树的“根”。

有关更多详细信息,请参见 Screens。 Active Screen(活动屏幕) ------------------------ .. raw:: html

<details>

<summary>显示原文</summary>

The Active Screen is the screen (and its child Widgets) currently being displayed. See Active Screen for more information. .. raw:: html

</details> <br>

活动屏幕是当前显示的屏幕(及其子小部件)。 有关更多信息,请参见 Active Screen。 .. _basics_widgets:

Widgets(小部件)

显示原文

After LVGL is initialized (see Initializing LVGL(初始化LVGL)), to create an interactive user interface, an application next creates a tree of Widgets that LVGL can render to the associated display, and with which the user can interact.

Widgets are "intelligent" LVGL graphical elements such as Base Widgets (simple rectangles and Screens), Buttons, Labels, Checkboxes, Switches, Sliders, Charts, etc. Go to Widgets(控件) to see the full list.

To build this Widget Tree, the application first acquires a pointer to a Screen Widget. A system designer is free to use the default Screen created with the Display (lv_display) and/or create his own. To create a new Screen Widget, simply create a Widget passing NULL as the parent argument. Technically, this can be any type of Widget, but in most cases it is a Base Widget(控件基础). (An example of another type of Widget being used as a Screen is an Image (图象)(lv_image) Widget to supply an image for the background.)

The application then adds Widgets to this Screen as children in the tree. Widgets are automatically added as children to their parent Widgets at time of creation --- the Widget's parent is passed as the first argument to the function that creates the Widget. After being so added, we say that the parent Widget "contains" the child Widget.

Any Widget can contain other Widgets. For example, if you want a Button to have text, create a Label Widget and add it to the Button as a child.

Each child Widget becomes "part of" its parent Widget. Because of this relationship:

  • when the parent Widget moves, its children move with it;

  • when the parent Widget is deleted, its children are deleted with it;

  • a child Widget is only visible within its parent's boundaries; any part of a child outside its parent's boundaries is clipped (i.e. not rendered).

Screens (and their child Widgets) can be created and deleted at any time except when the Screen is the Active Screen. If you want to delete the current Screen as you load a new one, call lv_screen_load_anim() and pass true for the auto_del argument. If you want to keep the current Screen in RAM when you load a new Screen, pass false for the auto_del argument, or call lv_screen_active() to load the new screen.

A system designer is free to keep any number of Screens (and their child Widgets) in RAM (e.g. for quick re-display again later). Doing so:

  • requires more RAM, but

  • can save the time of repeatedly creating the Screen and its child Widgets;

  • can be handy when a Screen is complex and/or can be made the Active Screen freqently.

If multiple Screens are maintained in RAM simultaneously, it is up to the system designer as to how they are managed. .. raw:: html

</details> <br>

在初始化 LVGL 之后(参见 Initializing LVGL(初始化LVGL)),为了创建一个交互式用户界面,应用程序接下来会创建一个小部件树,LVGL 可以将其渲染到相关显示器上,并与用户进行交互。

小部件是“智能”的 LVGL 图形元素,例如 基本小部件 <base_widget_overview>`(简单的矩形和 :ref:`屏幕)、按钮、标签、复选框、开关、滑块、图表等。请参见 Widgets(控件) 以查看完整列表。

为了构建这个小部件树,应用程序首先获取一个屏幕小部件的指针。系统设计人员可以自由使用与 Display (lv_display) 一起创建的默认屏幕和/或创建自己的屏幕。要创建一个新的屏幕小部件,只需在创建小部件时将父级参数传递为 NULL。从技术上讲,这可以是任何类型的小部件,但在大多数情况下,它是一个 基本小部件。(另一种用作屏幕的小部件类型的示例是 Image (图象)(lv_image) 小部件,用于提供背景图像。)

然后,应用程序将小部件作为树中的子节点添加到这个屏幕中。小部件在创建时会自动作为子节点添加到其父小部件中——小部件的父级作为创建小部件的函数的第一个参数传递。添加后,我们说父小部件“包含”子小部件。

任何小部件都可以包含其他小部件。例如,如果您希望按钮具有文本,请创建一个标签小部件并将其作为子节点添加到按钮中。

每个子小部件都成为其父小部件的“一部分”。由于这种关系:

  • 当父小部件移动时,其子小部件也会随之移动;

  • 当父小部件被删除时,其子小部件也会随之删除;

  • 子小部件仅在其父小部件的边界内可见;任何超出父小部件边界的子小部件部分都会被裁剪(即不渲染)。

屏幕(及其子小部件)可以在任何时候创建和删除 除了 当屏幕是 活动屏幕 时。如果您想在加载新屏幕时删除当前屏幕,请调用 lv_screen_load_anim() 并为 auto_del 参数传递 true。如果您想在加载新屏幕时将当前屏幕保留在 RAM 中,请为 auto_del 参数传递 false,或调用 lv_screen_active() 以加载新屏幕。

系统设计人员可以自由地在 RAM 中保留任意数量的屏幕(及其子小部件)(例如,以便稍后快速重新显示)。这样做:

  • 需要更多的 RAM,但

  • 可以节省反复创建屏幕及其子小部件的时间;

  • 当屏幕复杂且/或可以频繁成为 活动屏幕 时,这会很方便。

如果多个屏幕同时保存在 RAM 中,系统设计人员可以自行决定如何管理它们。 .. _basics_creating_widgets:

Creating Widgets(创建小部件)

显示原文

Widgets are created by calling functions that look like this:

lv_<type>_create(parent)

The call will return an lv_obj_t * pointer that can be used later to reference the Widget to set its attributes.

For example:

lv_obj_t * slider1 = lv_slider_create(lv_screen_active());

小部件是通过调用如下函数创建的:

lv_<type>_create(parent)

该调用将返回一个 lv_obj_t * 指针,稍后可以使用该指针引用小部件以设置其属性。

例如:

lv_obj_t * slider1 = lv_slider_create(lv_screen_active());

Modifying Widgets(修改小部件)

显示原文

Attributes common to all Widgets are set by functions that look like this:

lv_obj_set_<attribute_name>(widget, <value>)

For example:

lv_obj_set_x(slider1, 30);
lv_obj_set_y(slider1, 10);
lv_obj_set_size(slider1, 200, 50);

Along with these attributes, widgets can have type-specific attributes which are set by functions that look like this:

lv_<type>_set_<attribute_name>(widget, <value>)

For example:

lv_slider_set_value(slider1, 70, LV_ANIM_ON);

To see the full API visit the documentation of the Widget in question under Widgets(控件) or study its related header file in the source code, e.g.

  • lvgl/src/widgets/slider/lv_slider.h

or view it on GitHub, e.g.


所有小部件的通用属性通过如下函数设置:

lv_obj_set_<attribute_name>(widget, <value>)

例如:

lv_obj_set_x(slider1, 30);
lv_obj_set_y(slider1, 10);
lv_obj_set_size(slider1, 200, 50);

除了这些属性,小部件还可以有特定类型的属性,这些属性通过如下函数设置:

lv_<type>_set_<attribute_name>(widget, <value>)

例如:

lv_slider_set_value(slider1, 70, LV_ANIM_ON);

要查看完整的 API,请访问相关小部件的文档,参见 Widgets(控件) 或研究源代码中的相关头文件,例如:

  • lvgl/src/widgets/slider/lv_slider.h

或在 GitHub 上查看,例如:

Deleting Widgets(删除小部件)

显示原文

To delete any widget and its children:

lv_obj_delete(lv_obj_t * widget)

要删除任何小部件及其子小部件:

lv_obj_delete(lv_obj_t * widget)

Events(事件)

显示原文

Events are used to inform the application that something has happened with a Widget. You can assign one or more callbacks to a Widget which will be called when the Widget is clicked, released, dragged, being deleted, etc.

A callback is assigned like this:

lv_obj_add_event_cb(btn, my_btn_event_cb, LV_EVENT_CLICKED, NULL);

...

void my_btn_event_cb(lv_event_t * e)
{
    printf("Clicked\n");
}

LV_EVENT_ALL can be used instead of LV_EVENT_CLICKED to invoke the callback for all events. (Beware: there are a LOT of events! This can be handy for debugging or learning what events occur for a given Widget, or indeed if the application needs to process all events for some reason.)

Event callbacks receive the argument lv_event_t * e containing the current event code and other event-related information. The current event code can be retrieved with:

lv_event_code_t code = lv_event_get_code(e);

The Widget that triggered the event can be retrieved with:

lv_obj_t * obj = lv_event_get_target(e);

To learn all features of the events go to the Events(事件) section. .. raw:: html

</details> <br>

事件用于通知应用程序某个小部件发生了某些事情。 您可以为小部件分配一个或多个回调,当小部件被点击、释放、拖动、删除等时,这些回调将被调用。

回调的分配方式如下:

lv_obj_add_event_cb(btn, my_btn_event_cb, LV_EVENT_CLICKED, NULL);

...

void my_btn_event_cb(lv_event_t * e)
{
    printf("Clicked\n");
}

LV_EVENT_ALL 可以用来代替 LV_EVENT_CLICKED 以调用所有事件的回调。(注意:事件非常多!这对于调试或了解给定小部件发生了哪些事件很有用,或者如果应用程序由于某种原因需要处理所有事件,也很有用。)

事件回调接收参数 lv_event_t * e,其中包含当前事件代码和其他与事件相关的信息。可以使用以下代码检索当前事件代码:

lv_event_code_t code = lv_event_get_code(e);

可以使用以下代码检索触发事件的小部件:

lv_obj_t * obj = lv_event_get_target(e);

要了解事件的所有功能,请参见 Events(事件) 部分。 .. _basics_parts:

Parts(部件)

显示原文

Widgets are built from one or more parts. For example, a button has only one part called LV_PART_MAIN. However, a Slider (滑动条)(lv_slider) has LV_PART_MAIN, LV_PART_INDICATOR and LV_PART_KNOB.

By using parts you can apply different styles to sub-elements of a widget. (See below.)

Read the Widget's documentation to learn which parts it uses. .. raw:: html

</details> <br>

小部件由一个或多个*部件*构成。例如,一个按钮只有一个部件,称为 LV_PART_MAIN。然而,一个 Slider (滑动条)(lv_slider)LV_PART_MAINLV_PART_INDICATORLV_PART_KNOB

通过使用部件,您可以将不同的样式应用于小部件的子元素。(见下文。)

阅读小部件的文档以了解它使用了哪些部件。 .. _basics_states:

States(状态)

显示原文

Widgets can be in a combination of the following states:

For example, if you press a Widget it will automatically go to the LV_STATE_FOCUSED and LV_STATE_PRESSED states and when you release it the LV_STATE_PRESSED state will be removed while the LV_STATE_FOCUSED state remains active.

To check if a Widget is in a given state use lv_obj_has_state(widget, LV_STATE_...). It will return true if the Widget is currently in that state.

To manually add or remove states use:

lv_obj_add_state(widget, LV_STATE_...);
lv_obj_remove_state(widget, LV_STATE_...);

小部件可以处于以下状态的组合中:

例如,如果按下一个小部件,它将自动进入 LV_STATE_FOCUSEDLV_STATE_PRESSED 状态,当你释放它时,LV_STATE_PRESSED 状态将被移除,而 LV_STATE_FOCUSED 状态仍然保持活动。

要检查小部件是否处于给定状态,请使用 lv_obj_has_state(widget, LV_STATE_...)。如果小部件当前处于该状态,它将返回 true

要手动添加或移除状态,请使用:

lv_obj_add_state(widget, LV_STATE_...);
lv_obj_remove_state(widget, LV_STATE_...);

Styles(样式)

显示原文

A style instance contains properties such as background color, border width, font, etc. that describe the appearance of Widgets.

Styles are carried in lv_style_t objects. Only their pointer is saved in the Widgets so they need to be defined as static or global variables. Before using a style it needs to be initialized with lv_style_init(&style1). After that, properties can be added to configure the style. For example:

static lv_style_t style1;
lv_style_init(&style1);
lv_style_set_bg_color(&style1, lv_color_hex(0xa03080))
lv_style_set_border_width(&style1, 2))

See Style Properties Overview for more details.

See Style properties(样式属性) to see the full list.

Styles are assigned using the OR-ed combination of a Widget's part and state. For example to use this style on the slider's indicator when the slider is pressed:

lv_obj_add_style(slider1, &style1, LV_PART_INDICATOR | LV_STATE_PRESSED);

If the part is LV_PART_MAIN it can be omitted:

lv_obj_add_style(btn1, &style1, LV_STATE_PRESSED); /* Equal to LV_PART_MAIN | LV_STATE_PRESSED */

Similarly, LV_STATE_DEFAULT can be omitted:

lv_obj_add_style(slider1, &style1, LV_PART_INDICATOR); /* Equal to LV_PART_INDICATOR | LV_STATE_DEFAULT */

For LV_STATE_DEFAULT | LV_PART_MAIN simply pass 0:

lv_obj_add_style(btn1, &style1, 0); /* Equal to LV_PART_MAIN | LV_STATE_DEFAULT */

Styles can be cascaded (similarly to CSS). This means you can add more styles to a part of a Widget. For example style_btn can set a default button appearance, and style_btn_red can overwrite the background color to make the button red:

lv_obj_add_style(btn1, &style_btn, 0);
lv_obj_add_style(btn1, &style1_btn_red, 0);

If a property is not set for the current state, the style with LV_STATE_DEFAULT will be used. A default value is used if the property is not defined in the default state.

Some properties (particularly the text-related ones) can be inherited. This means if a property is not set in a Widget it will be searched for in its parents. For example, you can set the font once in the screen's style and all text on that screen will inherit it by default.

Local style properties also can be added to Widgets. This creates a style which resides inside the Widget and is used only by that Widget:

lv_obj_set_style_bg_color(slider1, lv_color_hex(0x2080bb), LV_PART_INDICATOR | LV_STATE_PRESSED);

To learn all the features of styles see Style Details(风格样式). .. raw:: html

</details> <br>

样式实例包含描述小部件外观的属性,例如背景颜色、边框宽度、字体等。

样式保存在 lv_style_t 对象中。只有它们的指针保存在小部件中,因此需要将它们定义为静态或全局变量。在使用样式之前,需要使用 lv_style_init(&style1) 进行初始化。之后,可以添加属性来配置样式。例如:

static lv_style_t style1;
lv_style_init(&style1);
lv_style_set_bg_color(&style1, lv_color_hex(0xa03080))
lv_style_set_border_width(&style1, 2))

有关更多详细信息,请参见 Style Properties Overview

要查看完整列表,请参见 Style properties(样式属性)

样式是通过小部件的部件和状态的按位或组合来分配的。例如,要在滑块被按下时将此样式用于滑块的指示器:

lv_obj_add_style(slider1, &style1, LV_PART_INDICATOR | LV_STATE_PRESSED);

如果 partLV_PART_MAIN,则可以省略:

lv_obj_add_style(btn1, &style1, LV_STATE_PRESSED); /* 等同于 LV_PART_MAIN | LV_STATE_PRESSED */

同样,LV_STATE_DEFAULT 也可以省略:

lv_obj_add_style(slider1, &style1, LV_PART_INDICATOR); /* 等同于 LV_PART_INDICATOR | LV_STATE_DEFAULT */

对于 LV_STATE_DEFAULT | LV_PART_MAIN,只需传递 0

lv_obj_add_style(btn1, &style1, 0); /* 等同于 LV_PART_MAIN | LV_STATE_DEFAULT */

样式可以级联(类似于 CSS)。这意味着您可以向小部件的某个部件添加更多样式。例如 style_btn 可以设置默认按钮外观,而 style_btn_red 可以覆盖背景颜色使按钮变红:

lv_obj_add_style(btn1, &style_btn, 0);
lv_obj_add_style(btn1, &style1_btn_red, 0);

如果当前状态未设置某个属性,则将使用 LV_STATE_DEFAULT 的样式。如果在默认状态下未定义该属性,则使用默认值。

某些属性(特别是与文本相关的属性)可以继承。这意味着如果在小部件中未设置某个属性,它将在其父级中搜索。例如,您可以在屏幕的样式中设置一次字体,屏幕上的所有文本将默认继承它。

本地样式属性也可以添加到小部件中。这会创建一个驻留在小部件内部并且仅由该小部件使用的样式:

lv_obj_set_style_bg_color(slider1, lv_color_hex(0x2080bb), LV_PART_INDICATOR | LV_STATE_PRESSED);

要了解样式的所有功能,请参见 Style Details(风格样式)。 .. _basics_themes:

Themes(主题)

显示原文

Themes are the default styles for Widgets. Styles from a theme are applied automatically when Widgets are created.

The theme for your application is a compile time configuration set in lv_conf.h. .. raw:: html

</details> <br>

主题是小部件的默认样式。主题中的样式在创建小部件时会自动应用。

应用程序的主题是在 lv_conf.h 中设置的编译时配置。 .. _basics_micropython:

MicroPython

显示原文

LVGL can even be used with MicroPython.

# Initialize
import display_driver
import lvgl as lv

# Create a button with a label
scr = lv.obj()
btn = lv.button(scr)
btn.align(lv.ALIGN.CENTER, 0, 0)
label = lv.label(btn)
label.set_text('Hello World!')
lv.screen_load(scr)

LVGL 甚至可以与 MicroPython 一起使用。

# 初始化
import display_driver
import lvgl as lv

# 创建一个带标签的按钮
scr = lv.obj()
btn = lv.button(scr)
btn.align(lv.ALIGN.CENTER, 0, 0)
label = lv.label(btn)
label.set_text('Hello World!')
lv.screen_load(scr)

Going Deeper(深入了解)

显示原文

There are several good ways ways to gain deeper knowledge of LVGL. Here is one recommended order of documents to read and things to play with while you are advancing your knowledge:

  1. If not already read, start with Introduction(介绍) page of the documentation. (5 minutes)

  2. Check out the Online Demos to see LVGL in action. (3 minutes)

  3. If not already done, read the LVGL Basics(LVGL 基础) (above). (15 minutes)

  4. Set up an LVGL Simulator on PC(PC端模拟器). (10 minutes)

  5. Have a look at some Examples(示例) and their code.

  6. Add LVGL to your project. See Add LVGL to Your Project(添加LVGL到你的工程) or check out the ready-to-use Projects.

  7. Read the main_components pages to get a better understanding of the library. (2-3 hours)

  8. Skim the documentation of Widgets(控件) to see what is available.

  9. If you have questions go to the Forum.

  10. Read the Contributing(贡献) guide to see how you can help to improve LVGL. (15 minutes)


有几种很好的方法可以深入了解 LVGL。以下是推荐的阅读文档顺序和在您提高知识时可以尝试的内容:

  1. 如果还没有阅读,请从文档的 Introduction(介绍) 页面开始。(5 分钟)

  2. 查看 在线演示 以了解 LVGL 的实际应用。(3 分钟)

  3. 如果还没有完成,请阅读 :ref:`lvgl_basics`(上文)。(15 分钟)

  4. 设置一个 LVGL Simulator on PC(PC端模拟器)。(10 分钟)

  5. 看看一些 Examples(示例) 及其代码。

  6. 将 LVGL 添加到您的项目中。参见 Add LVGL to Your Project(添加LVGL到你的工程) 或查看 现成的项目

  7. 阅读 main_components 页面以更好地理解该库。(2-3 小时)

  8. 浏览 Widgets(控件) 的文档以了解可用的内容。

  9. 如果有问题,请访问 论坛

  10. 阅读 Contributing(贡献) 指南,了解如何帮助改进 LVGL。(15 分钟)

Basic Examples(基本示例)

显示原文

Below are several basic examples. They include the application code that produces the Widget Tree needed to make LVGL render the examples shown. Each example assumes a LVGL has undergone normal initialization, meaning that a lv_display_t object was created and therefore has an Active Screen.


以下是几个基本示例。它们包含生成小部件树的应用程序代码,以使 LVGL 渲染所示示例。每个示例都假设 LVGL 已经进行了正常初始化,这意味着创建了一个 lv_display_t 对象,因此有一个 Active Screen

A very simple hello world label

#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_LABEL

/**
 * Basic example to create a "Hello world" label
 */
void lv_example_get_started_1(void)
{
    /*Change the active screen's background color*/
    lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0x003a57), LV_PART_MAIN);

    /*Create a white label, set its text and align it to the center*/
    lv_obj_t * label = lv_label_create(lv_screen_active());
    lv_label_set_text(label, "Hello world");
    lv_obj_set_style_text_color(lv_screen_active(), lv_color_hex(0xffffff), LV_PART_MAIN);
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
}

#endif

A button with a label and react on click event

#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_BUTTON

static void btn_event_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * btn = lv_event_get_target(e);
    if(code == LV_EVENT_CLICKED) {
        static uint8_t cnt = 0;
        cnt++;

        /*Get the first child of the button which is the label and change its text*/
        lv_obj_t * label = lv_obj_get_child(btn, 0);
        lv_label_set_text_fmt(label, "Button: %d", cnt);
    }
}

/**
 * Create a button with a label and react on click event.
 */
void lv_example_get_started_2(void)
{
    lv_obj_t * btn = lv_button_create(lv_screen_active());     /*Add a button the current screen*/
    lv_obj_set_pos(btn, 10, 10);                            /*Set its position*/
    lv_obj_set_size(btn, 120, 50);                          /*Set its size*/
    lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL);           /*Assign a callback to the button*/

    lv_obj_t * label = lv_label_create(btn);          /*Add a label to the button*/
    lv_label_set_text(label, "Button");                     /*Set the labels text*/
    lv_obj_center(label);
}

#endif

Create styles from scratch for buttons

#include "../lv_examples.h"
#if LV_USE_BUTTON && LV_BUILD_EXAMPLES

static lv_style_t style_btn;
static lv_style_t style_button_pressed;
static lv_style_t style_button_red;

static lv_color_t darken(const lv_color_filter_dsc_t * dsc, lv_color_t color, lv_opa_t opa)
{
    LV_UNUSED(dsc);
    return lv_color_darken(color, opa);
}

static void style_init(void)
{
    /*Create a simple button style*/
    lv_style_init(&style_btn);
    lv_style_set_radius(&style_btn, 10);
    lv_style_set_bg_opa(&style_btn, LV_OPA_COVER);
    lv_style_set_bg_color(&style_btn, lv_palette_lighten(LV_PALETTE_GREY, 3));
    lv_style_set_bg_grad_color(&style_btn, lv_palette_main(LV_PALETTE_GREY));
    lv_style_set_bg_grad_dir(&style_btn, LV_GRAD_DIR_VER);

    lv_style_set_border_color(&style_btn, lv_color_black());
    lv_style_set_border_opa(&style_btn, LV_OPA_20);
    lv_style_set_border_width(&style_btn, 2);

    lv_style_set_text_color(&style_btn, lv_color_black());

    /*Create a style for the pressed state.
     *Use a color filter to simply modify all colors in this state*/
    static lv_color_filter_dsc_t color_filter;
    lv_color_filter_dsc_init(&color_filter, darken);
    lv_style_init(&style_button_pressed);
    lv_style_set_color_filter_dsc(&style_button_pressed, &color_filter);
    lv_style_set_color_filter_opa(&style_button_pressed, LV_OPA_20);

    /*Create a red style. Change only some colors.*/
    lv_style_init(&style_button_red);
    lv_style_set_bg_color(&style_button_red, lv_palette_main(LV_PALETTE_RED));
    lv_style_set_bg_grad_color(&style_button_red, lv_palette_lighten(LV_PALETTE_RED, 3));
}

/**
 * Create styles from scratch for buttons.
 */
void lv_example_get_started_3(void)
{
    /*Initialize the style*/
    style_init();

    /*Create a button and use the new styles*/
    lv_obj_t * btn = lv_button_create(lv_screen_active());
    /* Remove the styles coming from the theme
     * Note that size and position are also stored as style properties
     * so lv_obj_remove_style_all will remove the set size and position too */
    lv_obj_remove_style_all(btn);
    lv_obj_set_pos(btn, 10, 10);
    lv_obj_set_size(btn, 120, 50);
    lv_obj_add_style(btn, &style_btn, 0);
    lv_obj_add_style(btn, &style_button_pressed, LV_STATE_PRESSED);

    /*Add a label to the button*/
    lv_obj_t * label = lv_label_create(btn);
    lv_label_set_text(label, "Button");
    lv_obj_center(label);

    /*Create another button and use the red style too*/
    lv_obj_t * btn2 = lv_button_create(lv_screen_active());
    lv_obj_remove_style_all(btn2);                      /*Remove the styles coming from the theme*/
    lv_obj_set_pos(btn2, 10, 80);
    lv_obj_set_size(btn2, 120, 50);
    lv_obj_add_style(btn2, &style_btn, 0);
    lv_obj_add_style(btn2, &style_button_red, 0);
    lv_obj_add_style(btn2, &style_button_pressed, LV_STATE_PRESSED);
    lv_obj_set_style_radius(btn2, LV_RADIUS_CIRCLE, 0); /*Add a local style too*/

    label = lv_label_create(btn2);
    lv_label_set_text(label, "Button 2");
    lv_obj_center(label);
}

#endif

Create a slider and write its value on a label

#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_SLIDER

static lv_obj_t * label;

static void slider_event_cb(lv_event_t * e)
{
    lv_obj_t * slider = lv_event_get_target(e);

    /*Refresh the text*/
    lv_label_set_text_fmt(label, "%"LV_PRId32, lv_slider_get_value(slider));
    lv_obj_align_to(label, slider, LV_ALIGN_OUT_TOP_MID, 0, -15);    /*Align top of the slider*/
}

/**
 * Create a slider and write its value on a label.
 */
void lv_example_get_started_4(void)
{
    /*Create a slider in the center of the display*/
    lv_obj_t * slider = lv_slider_create(lv_screen_active());
    lv_obj_set_width(slider, 200);                          /*Set the width*/
    lv_obj_center(slider);                                  /*Align to the center of the parent (screen)*/
    lv_obj_add_event_cb(slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);     /*Assign an event function*/

    /*Create a label above the slider*/
    label = lv_label_create(lv_screen_active());
    lv_label_set_text(label, "0");
    lv_obj_align_to(label, slider, LV_ALIGN_OUT_TOP_MID, 0, -15);    /*Align top of the slider*/
}

#endif