[English]

Widget Basics

What is a Widget?

显示原文

A Widget is the basic building block of the LVGL user interface.

Examples of Widgets: Base Widget (and Screen), Button, Label, Image, List, Chart and Text Area.

See Widgets(控件) to see all Widget types.

All Widgets are referenced using an lv_obj_t pointer as a handle. This pointer can later be used to read or change the Widget's attributes.


Widget 是 LVGL 用户界面的**基本构建块**。

Widget 的例子有:Base Widget(和 Screen)ButtonLabelImageListChartText Area

参见 Widgets(控件) 以查看所有类型的 Widget。

所有 Widget 都使用一个 lv_obj_t 指针作为句柄进行引用。 此指针稍后可用于读取或更改 Widget 的属性。

Base Widget

显示原文

The most fundamental of all Widgets is the Base Widget, on which all other widgets are based. From an Object-Oriented perspective, think of the Base Widget as the Widget class from which all other Widgets inherit.

The functions and functionalities of the Base Widget can be used with other widgets as well. For example lv_obj_set_width(slider, 100).

The Base Widget can be used directly as a simple widget. While it is a simple rectangle, it has a large number of features shared with all Widgets, detailed below and in subsequent pages. In HTML terms, think of it as a <div>.


所有 Widgets 中最基本的是基础 Widget,所有其他 Widgets 都基于它构建。从面向对象的角度来看,可以将基础 Widget 视作所有其他 Widgets 继承的 Widget 类。

基础 Widget 的函数和功能也可以与其他 Widgets 一起使用。例如 lv_obj_set_width(slider, 100)

基础 Widget 可以直接用作一个简单的 Widget。虽然它只是一个简单的矩形,但它具有与所有 Widgets 共享的大量特性,这些将在下文及后续页面中详细介绍。用 HTML 的术语来说,可以把它看作是一个 <div>

Attributes

Basic attributes

显示原文

All Widget types share some basic attributes:

  • Position

  • Size

  • Parent

  • Styles

  • Events it emits

  • Flags like Clickable, Scollable, etc.

  • Etc.

You can set/get these attributes with lv_obj_set_... and lv_obj_get_... functions. For example:

/* Set basic Widget attributes */
lv_obj_set_size(btn1, 100, 50);   /* Set a button's size */
lv_obj_set_pos(btn1, 20,30);      /* Set a button's position */

For complete details on position, size, coordinates and layouts, see Positions, sizes, and layouts(位置、大小和布局).


所有 Widget 类型共享一些基本属性:

  • 位置

  • 尺寸

  • 父级

  • 样式

  • 它发出的事件

  • 标志,如 Clickable, Scollable

  • 等等

您可以使用 lv_obj_set_...lv_obj_get_... 函数来设置/获取这些属性。例如:

/* 设置基本 Widget 属性 */
lv_obj_set_size(btn1, 100, 50);   /* 设置按钮的尺寸 */
lv_obj_set_pos(btn1, 20, 30);     /* 设置按钮的位置 */

有关位置、尺寸、坐标和布局的完整详细信息,请参见 Positions, sizes, and layouts(位置、大小和布局)

Widget-specific attributes

显示原文

The Widget types have special attributes as well. For example, a slider has

  • Minimum and maximum values

  • Current value

For these special attributes, every Widget type may have unique API functions. For example for a slider:

/* Set slider specific attributes */
lv_slider_set_range(slider1, 0, 100);               /* Set the min. and max. values */
lv_slider_set_value(slider1, 40, LV_ANIM_ON);       /* Set the current value (position) */

The API of the widgets is described in their Documentation but you can also check the respective header files (e.g. widgets/lv_slider.h)


Widget 类型还具有特殊的属性。例如,滑块(slider)有

  • 最小值和最大值

  • 当前值

对于这些特殊属性,每种 Widget 类型可能都有独特的 API 函数。例如对于滑块(slider):

/* 设置滑块特有的属性 */
lv_slider_set_range(slider1, 0, 100);               /* 设置最小值和最大值 */
lv_slider_set_value(slider1, 40, LV_ANIM_ON);       /* 设置当前值(位置),并开启动画 */

Widget 的 API 在其 Documentation 中有描述,您也可以检查相应的头文件(例如 widgets/lv_slider.h)。

Parents and children

显示原文

A Widget's parent is set when the widget is created --- the parent is passed to the creation function.

To get a Widget's current parent, use lv_obj_get_parent(widget).

You can move the Widget to a new parent with lv_obj_set_parent(widget, new_parent).

To get a specific child of a parent use lv_obj_get_child(parent, idx). Some examples for idx:

  • 0 get the child created first

  • 1 get the child created second

  • -1 get the child created last

You can iterate through a parent Widget's children like this:

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(widget) returns the index of the Widget in its parent. It is equivalent to the number of older children in the parent.

You can bring a Widget to the foreground or send it to the background with lv_obj_move_foreground(widget) and lv_obj_move_background(widget).

You can change the index of a Widget in its parent using lv_obj_move_to_index(widget, index).

You can swap the position of two Widgets with lv_obj_swap(widget1, widget2).

To get a Widget's Screen (highest-level parent) use lv_obj_get_screen(widget).


Widget 的父级是在创建 Widget 时设置的——父级被传递给创建函数。

要获取 Widget 的当前父级,使用 lv_obj_get_parent(widget)

你可以使用 lv_obj_set_parent(widget, new_parent) 将 Widget 移动到一个新的父级。

要获取父级的特定子 Widget,使用 lv_obj_get_child(parent, idx)idx 的一些例子如下:

  • 0 获取最先创建的子 Widget

  • 1 获取第二个创建的子 Widget

  • -1 获取最后创建的子 Widget

你可以像这样迭代一个父级 Widget 的所有子 Widget:

uint32_t i;
for(i = 0; i < lv_obj_get_child_count(parent); i++) {
    lv_obj_t * child = lv_obj_get_child(parent, i);
    /* 对子 Widget 执行某些操作。*/
}

lv_obj_get_index(widget) 返回 Widget 在其父级中的索引。它相当于在父级中比它早创建的子 Widget 数量。

你可以使用 lv_obj_move_foreground(widget)lv_obj_move_background(widget) 将 Widget 移动到前景或发送到背景。

你可以使用 lv_obj_move_to_index(widget, index) 改变 Widget 在其父级中的索引。

你可以使用 lv_obj_swap(widget1, widget2) 交换两个 Widget 的位置。

要获取 Widget 的 Screen(最高级别的父级),使用 lv_obj_get_screen(widget)

Working Mechanisms

Parent-child structure

显示原文

A parent Widget can be considered as the container of its children. Every Widget has exactly one parent Widget (except Screens), but a parent Widget can have any number of children. There is no limitation for the type of the parent but there are Widgets which are typically a parent (e.g. button) or a child (e.g. label).


一个父级 Widget 可以被视为其子 Widget 的容器。每个 Widget 恰好有一个父级 Widget(除了 Screens 之外), 但是一个父级 Widget 可以拥有任意数量的子 Widget。 对于父级的类型没有限制,但有一些通常是作为父级的 Widgets(例如按钮 button)或作为子级的 Widgets(例如标签 label)。

Moving together

显示原文

If the position of a parent changes, the children will move along with it. Therefore, all positions are relative to the parent.

../../_images/par_child1.png
lv_obj_t * parent = lv_obj_create(lv_screen_active());  /* Create a parent Widget on current screen */
lv_obj_set_size(parent, 100, 80);                       /* Set size of parent */

lv_obj_t * obj1 = lv_obj_create(parent);                /* Create a Widget on previously created parent Widget */
lv_obj_set_pos(widget1, 10, 10);                        /* Set position of new Widget */

Modify the position of the parent:

../../_images/par_child2.png
lv_obj_set_pos(parent, 50, 50); /* Move the parent. The child will move with it. */

(For simplicity the adjusting of colors of the Widgets is not shown in the example.)


如果父级的位置发生变化,子 Widget 将会随之移动。因此,所有位置都是相对于父级的。

../../_images/par_child1.png
lv_obj_t * parent = lv_obj_create(lv_screen_active());  /* 在当前屏幕上创建一个父级 Widget */
lv_obj_set_size(parent, 100, 80);                       /* 设置父级的尺寸 */

lv_obj_t * obj1 = lv_obj_create(parent);                /* 在先前创建的父级 Widget 上创建一个 Widget */
lv_obj_set_pos(widget1, 10, 10);                        /* 设置新 Widget 的位置 */

修改父级的位置:

../../_images/par_child2.png
lv_obj_set_pos(parent, 50, 50); /* 移动父级。子级将随之移动。 */

(为了简化起见,本例中未显示调整 Widget 颜色的操作。)

Visibility only on the parent

显示原文

If a child is partially or fully outside its parent then the parts outside will not be visible.

../../_images/par_child3.png
lv_obj_set_x(widget1, -30);    /* Move the child a little bit off the parent */

This behavior can be overwritten with lv_obj_add_flag(widget, LV_OBJ_FLAG_OVERFLOW_VISIBLE) which allow the children to be drawn out of the parent. In addition to this, you must register the following event callback (this was not required in previous versions).

Note: ext_width should be the maximum absolute width the children will be drawn within.

static void ext_draw_size_event_cb(lv_event_t * e)
{
    lv_event_set_ext_draw_size(e, 30); /*Set 30px extra draw area around the widget*/
}

如果子级部分或完全位于其父级之外,则外部的部分将不会被显示。

../../_images/par_child3.png
lv_obj_set_x(widget1, -30);    /* 将子级稍微移出父级 */

这种行为可以通过 lv_obj_add_flag(widget, LV_OBJ_FLAG_OVERFLOW_VISIBLE) 来覆盖,它允许子级在父级之外绘制。除此之外,你必须注册以下事件回调(这在之前的版本中是不需要的)。

注意: ext_width 应该是子级将被绘制在内的最大绝对宽度。

static void ext_draw_size_event_cb(lv_event_t * e)
{
    lv_event_set_ext_draw_size(e, 30); /* 设置 widget 周围 30px 的额外绘制区域 */
}

Create and delete Widgets

显示原文

In LVGL, Widgets can be created and deleted dynamically at run time. It means only the currently created (existing) Widgets consume RAM.

This allows for the creation of a screen just when a button is clicked to open it, and for deletion of screens when a new screen is loaded.

UIs can be created based on the current environment of the device. For example one can create meters, charts, bars and sliders based on the currently attached sensors.

Every widget has its own create function with a prototype like this:

lv_obj_t * lv_<widget>_create(lv_obj_t * parent, <other parameters if any>);

Typically, the create functions only have a parent parameter telling them on which Widget to create the new Widget.

The return value is a pointer to the created Widget with lv_obj_t * type.

There is a common delete function for all Widget types. It deletes the Widget and all of its children.

void lv_obj_delete(lv_obj_t * widget);

lv_obj_delete() will delete the Widget immediately. If for any reason you can't delete the Widget immediately you can use lv_obj_delete_async(widget) which will perform the deletion on the next call of lv_timer_handler(). This is useful e.g. if you want to delete the parent of a Widget in the child's LV_EVENT_DELETE handler.

You can remove all the children of a Widget (but not the Widget itself) using lv_obj_clean(widget).

You can use lv_obj_delete_delayed(widget, 1000) to delete a Widget after some time. The delay is expressed in milliseconds.

Sometimes you're not sure whether a Widget was deleted and you need some way to check if it's still "alive". Anytime before the Widget is deleted, you can use cpp:expr:lv_obj_null_on_delete(&widget) to cause your Widget pointer to be set to NULL when the Widget is deleted.

Make sure the pointer variable itself stays valid until the Widget is deleted. Here is an example:

void some_timer_callback(lv_timer_t * t)
{
   static lv_obj_t * my_label;
   if(my_label == NULL) {
      my_label = lv_label_create(lv_screen_active());
      lv_obj_delete_delayed(my_label, 1000);
      lv_obj_null_on_delete(&my_label);
   }
   else {
      lv_obj_set_x(my_label, lv_obj_get_x(my_label) + 1);
   }
}

在 LVGL 中,Widgets 可以在运行时动态创建和删除。这意味着只有当前创建(存在的)Widgets 会消耗 RAM。

这允许在一个按钮被点击打开一个屏幕时创建该屏幕,并在加载新屏幕时删除旧屏幕。

用户界面可以根据设备的当前环境创建。例如,可以基于当前连接的传感器创建仪表、图表、条形图和滑块。

每个 widget 都有自己的 create 函数,其原型如下:

lv_obj_t * lv_<widget>_create(lv_obj_t * parent, <other parameters if any>);

通常,创建函数仅有一个 parent 参数,用于告知在哪个 Widget 上创建新的 Widget。

返回值是指向创建的 Widget 的指针,类型为 lv_obj_t *

所有 Widget 类型都有一个通用的 delete 函数。它会删除 Widget 及其所有子级。

void lv_obj_delete(lv_obj_t * widget);

lv_obj_delete() 将立即删除 Widget。如果由于任何原因不能立即删除 Widget,你可以使用 lv_obj_delete_async(widget),它将在下一次调用 lv_timer_handler() 时执行删除操作。这在你想要在子级的 LV_EVENT_DELETE 处理程序中删除父级 Widget 时非常有用。

你可以通过 lv_obj_clean(widget) 移除 Widget 的所有子级(但不包括 Widget 本身)。

你可以使用 lv_obj_delete_delayed(widget, 1000) 在一段时间后删除 Widget。延迟是以毫秒为单位表示的。

有时你不确定 Widget 是否已被删除,并且需要某种方法来检查它是否仍然“存活”。在 Widget 被删除之前任何时候,你可以使用 cpp:expr:lv_obj_null_on_delete(&widget),以便在 Widget 被删除时将其指针设置为 NULL

确保指针变量本身保持有效直到 Widget 被删除。以下是一个示例:

void some_timer_callback(lv_timer_t * t)
{
   static lv_obj_t * my_label;
   if(my_label == NULL) {
      my_label = lv_label_create(lv_screen_active());
      lv_obj_delete_delayed(my_label, 1000);
      lv_obj_null_on_delete(&my_label);
   }
   else {
      lv_obj_set_x(my_label, lv_obj_get_x(my_label) + 1);
   }
}

Screens

What are Screens?

显示原文

Not to be confused with a Displays(显示), Screens are simply any Widget created without a parent (i.e. passing NULL for the parent argument during creation). As such, they form the "root" of a Widget Tree.

Normally the Base Widget is used for this purpose since it has all the features most Screens need. But an Image (图象)(lv_image) Widget can also be used to create a wallpaper background for the Widget Tree.

All Screens:

  • are automatically attached to the default_display current when the Screen was created;

  • automatically occupy the full area of the associated display;

  • cannot be moved, i.e. functions such as lv_obj_set_pos() and lv_obj_set_size() cannot be used on screens.

Each Displays(显示) object can have multiple screens associated with it, but not vice versa. Thus the relationship:

   Display
      |
     --- (one or more)
     /|\
Screen Widgets  (root of a Widget Tree)
      |
      O  (zero or more)
     /|\
Child Widgets

不要与 Displays(显示) 混淆,Screens 仅仅是创建时不带父级(即在创建时为 parent 参数传递 NULL)的任何 Widget。因此,它们构成了 Widget 树的“根”。

通常情况下,基础 Widget 用于此目的,因为它具备大多数 Screens 所需的所有特性。但是,也可以使用 Image (图象)(lv_image) Widget 来为 Widget 树创建壁纸背景。

所有 Screens:

  • 在创建 Screen 时自动附加到 default_display

  • 自动占用关联显示的整个区域;

  • 不能被移动,即不能在屏幕上使用诸如 lv_obj_set_pos()lv_obj_set_size() 等函数。

每个 Displays(显示) 对象可以有多个与之关联的 Screens,但反之则不行。因此关系如下:

   Display
      |
     --- 一个或多个
     /|\
Screen Widgets  Widget 树的根
      |
      O  零个或多个
     /|\
Child Widgets

Creating Screens

显示原文

Screens are created like this:

lv_obj_t * scr1 = lv_obj_create(NULL);

Screens can be deleted with lv_obj_delete(scr), but be sure you do not delete the Active Screen.


Screens 是这样创建的:

lv_obj_t * scr1 = lv_obj_create(NULL);

可以使用 lv_obj_delete(scr) 删除 Screens,但请确保不要删除 Active Screen

Active Screen

显示原文

While each Displays(显示) object can have any number of Screens Widgets associated with it, only one of those Screens is considered "Active" at any given time. That Screen is referred to as the Display's "Active Screen". For this reason, only one Screen and its child Widgets will ever be shown on a display at one time.

When each Displays(显示) object was created, a default screen was created with it and set as its "Active Screen".

To get a pointer to the "Active Screen", call lv_screen_active().

To set a Screen to be the "Active Screen", call lv_screen_load() or lv_screen_load_anim().


虽然每个 Displays(显示) 对象可以有关联的任意数量的 Screen Widgets,但在任何给定时间只考虑其中一个 Screen 是“Active”的。该 Screen 被称为 Display 的“Active Screen”。因此,一次只有一个 Screen 及其子 Widgets 会在一个显示上显示。

当每个 Displays(显示) 对象被创建时,会与之一起创建一个默认屏幕,并设置为其“Active Screen”。

要获取指向“Active Screen”的指针,请调用 lv_screen_active()

要将一个 Screen 设置为“Active Screen”,请调用 lv_screen_load()lv_screen_load_anim()

Loading Screens

显示原文

To load a new screen, use lv_screen_load(scr1). This sets scr1 as the Active Screen.


要加载新屏幕,请使用:cpp:expr:lv_screen_load(scr1)。这将 ``scr1``设置为 活动屏幕。

Load Screen with Animation

显示原文

A new screen can be loaded with animation by using lv_screen_load_anim(scr, transition_type, time, delay, auto_del). The following transition types exist:

Setting auto_del to true will automatically delete the old screen when the animation is finished.

The new screen will become active (returned by lv_screen_active()) when the animation starts after delay time. All inputs are disabled during the screen animation.


可以通过使用 lv_screen_load_anim(scr, transition_type, time, delay, auto_del) 带动画加载新的屏幕。存在以下过渡类型:

auto_del 设置为 true 会在动画结束后自动删除旧的屏幕。

新屏幕将在 delay 时间过后,当动画开始时变为活动状态(由 lv_screen_active() 返回)。在屏幕动画期间,所有输入都将被禁用。

Layers

显示原文

When an lv_display_t object is created, 4 Screens (layers) are created and attached to it.

  1. Bottom Layer

  2. Active Screen

  3. Top Layer

  4. System Layer

1, 3 and 4 are independent of the Active Screen and they will be shown (if they contain anything that is visible) regardless of which screen is the Active Screen. See screen_layers for more information.


当创建一个 lv_display_t 对象时,会创建4个 Screens(层)并附着到它上面。

  1. Bottom Layer

  2. Active Screen

  3. Top Layer

  4. System Layer

1、3 和 4 层独立于 Active Screen,如果它们包含任何可见的内容,则无论哪个屏幕是 Active Screen 都会显示。更多详情请参见 screen_layers

Transparent Screens

显示原文

Usually, the opacity of the Screen is LV_OPA_COVER to provide a solid background for its children. If this is not the case (opacity < 100%) the display's bottom_layer will be visible. If the bottom layer's opacity is also not LV_OPA_COVER LVGL will have no solid background to draw.

This configuration (transparent Screen) could be useful to create, for example, on-screen display (OSD) menus where a video is played on a different hardware layer of the display panel, and a menu is overlaid on a higher layer.

To properly render a UI on a transparent Screen the Display's color format needs to be set to one with an alpha channel (for example LV_COLOR_FORMAT_ARGB8888).

In summary, to enable transparent screens and displays for OSD menu-like UIs:


通常,Screen 的不透明度为 LV_OPA_COVER 以为其子级提供一个实心背景。如果不是这种情况(不透明度 < 100%),则 display 的 bottom_layer 将会可见。如果 bottom layer 的不透明度也非 LV_OPA_COVER,LVGL 将没有实心背景来绘制。

这种配置(透明 Screen)对于创建例如屏幕显示(OSD)菜单非常有用,在这种情况下,视频在一个不同的硬件层播放,而菜单则覆盖在显示器面板的更高层上。

为了正确地在透明屏幕上渲染 UI,display 的颜色格式需要设置为带有 alpha 通道的一种(例如 LV_COLOR_FORMAT_ARGB8888)。

总而言之,要启用适用于类似 OSD 菜单 UI 的透明屏幕和显示:

Parts

显示原文

The widgets are built from multiple parts. For example a Base Widget uses the main and scrollbar parts but a Slider uses the main, indicator and knob parts. Parts are similar to pseudo-elements in CSS.

The following predefined parts exist in LVGL:

The main purpose of parts is to allow styling the "components" of the widgets. They are described in more detail in the Style overview section.


Widgets 是由多个部分构建而成的。例如,Base Widget 使用主部分和滚动条部分,而 Slider 则使用主部分、指示器部分和旋钮部分。这些部分类似于 CSS 中的 伪元素

LVGL 中存在以下预定义的部分:

部分的主要目的是允许对 Widgets 的“组件”进行样式设置。它们在 Style overview 部分中有更详细的描述。

States

显示原文

The Widget can be in a combination of the following states:

The states are usually automatically changed by the library as the user interacts with a Widget (presses, releases, focuses, etc.). However, the states can be changed manually as well. To set or clear given state (but leave the other states untouched) use lv_obj_add_state(widget, LV_STATE_...) and lv_obj_remove_state(widget, LV_STATE_...). In both cases OR-ed state values can be used as well. E.g. lv_obj_add_state(widget, part, LV_STATE_PRESSED | LV_PRESSED_CHECKED).

To learn more about the states read the related section of the Style overview.


Widget 可以处于以下状态的组合中:

这些状态通常由库根据用户与 Widget 的交互(按压、释放、聚焦等)自动更改。然而,也可以手动更改状态。要设置或清除给定状态(但保留其他状态不变),请使用 lv_obj_add_state(widget, LV_STATE_...)lv_obj_remove_state(widget, LV_STATE_...)。在这两种情况下都可以使用 OR 连接的状态值。例如: lv_obj_add_state(widget, part, LV_STATE_PRESSED | LV_STATE_CHECKED)

要了解更多关于状态的信息,请阅读 Style overview 的相关部分。

Flags

显示原文

There are some Widget attributes which can be enabled/disabled by lv_obj_add_flag(widget, LV_OBJ_FLAG_...) and lv_obj_remove_flag(widget, LV_OBJ_FLAG_...).

Some examples:

/* Hide on Widget */
lv_obj_add_flag(widget, LV_OBJ_FLAG_HIDDEN);

/* Make a Widget non-clickable */
lv_obj_remove_flag(widget, LV_OBJ_FLAG_CLICKABLE);

有一些 Widget 属性可以通过 lv_obj_add_flag(widget, LV_OBJ_FLAG_...)lv_obj_remove_flag(widget, LV_OBJ_FLAG_...) 来启用或禁用。

一些例子:

/* 隐藏 Widget */
lv_obj_add_flag(widget, LV_OBJ_FLAG_HIDDEN);

/* 使 Widget 不可点击 */
lv_obj_remove_flag(widget, LV_OBJ_FLAG_CLICKABLE);

Base-Widget Events

Events from Input Devices

显示原文

Special Events

显示原文

Drawing Events

显示原文

Other Events

显示原文

Further Reading

Learn more about Events(事件).


Further Reading

Learn more about Events(事件).

Keys

显示原文

If LV_OBJ_FLAG_CHECKABLE is enabled, LV_KEY_RIGHT and LV_KEY_UP make the Widget checked, and LV_KEY_LEFT and LV_KEY_DOWN make it unchecked.

If LV_OBJ_FLAG_SCROLLABLE is enabled, but the Widget is not editable (as declared by the widget class), the arrow keys (LV_KEY_UP, LV_KEY_DOWN, LV_KEY_LEFT, LV_KEY_RIGHT) scroll the Widget. If the Widget can only scroll vertically, LV_KEY_LEFT and LV_KEY_RIGHT will scroll up/down instead, making it compatible with an encoder input device. See Input devices overview for more on encoder behaviors and the edit mode.

Further Reading

Learn more about Keys(按键).


如果启用了 LV_OBJ_FLAG_CHECKABLELV_KEY_RIGHTLV_KEY_UP 会使 Widget 处于选中状态,而 LV_KEY_LEFTLV_KEY_DOWN 则使其取消选中。

如果启用了 LV_OBJ_FLAG_SCROLLABLE,但 Widget 不是可编辑的 (由 widget 类声明),那么箭头键 (LV_KEY_UPLV_KEY_DOWNLV_KEY_LEFTLV_KEY_RIGHT) 将滚动 Widget。 如果 Widget 仅能垂直滚动,则 LV_KEY_LEFTLV_KEY_RIGHT 将改为上下滚动,使其与编码器输入设备兼容。关于编码器行为和编辑模式的更多信息,请参阅 Input devices overview

Further Reading

了解更多关于 Keys(按键) 的信息。

Snapshot

显示原文

A snapshot image can be generated for a Widget together with its children. Check details in Snapshot(快照).


可以为小部件生成快照图像及其 孩子们。查看详情 Snapshot(快照)

Example

[English]

Base objects with custom styles

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

void lv_example_obj_1(void)
{
    lv_obj_t * obj1;
    obj1 = lv_obj_create(lv_screen_active());
    lv_obj_set_size(obj1, 100, 50);
    lv_obj_align(obj1, LV_ALIGN_CENTER, -60, -30);

    static lv_style_t style_shadow;
    lv_style_init(&style_shadow);
    lv_style_set_shadow_width(&style_shadow, 10);
    lv_style_set_shadow_spread(&style_shadow, 5);
    lv_style_set_shadow_color(&style_shadow, lv_palette_main(LV_PALETTE_BLUE));

    lv_obj_t * obj2;
    obj2 = lv_obj_create(lv_screen_active());
    lv_obj_add_style(obj2, &style_shadow, 0);
    lv_obj_align(obj2, LV_ALIGN_CENTER, 60, 30);
}
#endif

Make an object draggable

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

static void drag_event_handler(lv_event_t * e)
{
    lv_obj_t * obj = lv_event_get_target(e);

    lv_indev_t * indev = lv_indev_active();
    if(indev == NULL)  return;

    lv_point_t vect;
    lv_indev_get_vect(indev, &vect);

    int32_t x = lv_obj_get_x_aligned(obj) + vect.x;
    int32_t y = lv_obj_get_y_aligned(obj) + vect.y;
    lv_obj_set_pos(obj, x, y);
}

/**
 * Make an object draggable.
 */
void lv_example_obj_2(void)
{
    lv_obj_t * obj;
    obj = lv_obj_create(lv_screen_active());
    lv_obj_set_size(obj, 150, 100);
    lv_obj_add_event_cb(obj, drag_event_handler, LV_EVENT_PRESSING, NULL);

    lv_obj_t * label = lv_label_create(obj);
    lv_label_set_text(label, "Drag me");
    lv_obj_center(label);

}
#endif

Transform object using a 3x3 matrix

#include "../../lv_examples.h"
#if LV_BUILD_EXAMPLES
#if LV_DRAW_TRANSFORM_USE_MATRIX

static void timer_cb(lv_timer_t * timer)
{
    lv_obj_t * obj = lv_timer_get_user_data(timer);

    static float value = 0.1f;
    lv_matrix_t matrix;
    lv_matrix_identity(&matrix);
    lv_matrix_scale(&matrix, value, 1);
    lv_matrix_rotate(&matrix, value * 360);
    lv_obj_set_transform(obj, &matrix);

    value += 0.01f;

    if(value > 2.0f) {
        lv_obj_reset_transform(obj);
        value = 0.1f;
    }
}

void lv_example_obj_3(void)
{
    lv_obj_t * obj = lv_obj_create(lv_screen_active());
    lv_obj_center(obj);

    lv_timer_create(timer_cb, 20, obj);
}

#else

void lv_example_obj_3(void)
{
    lv_obj_t * label = lv_label_create(lv_screen_active());
    lv_label_set_text_static(label, "LV_DRAW_TRANSFORM_USE_MATRIX is not enabled");
    lv_obj_center(label);
}

#endif /*LV_DRAW_TRANSFORM_USE_MATRIX*/
#endif /*LV_BUILD_EXAMPLES*/

API

lv_flex.h

lv_obj_property_names.h

lv_obj_style.h

lv_types.h

lv_grid.h

lv_obj_class.h

lv_obj_scroll.h

lv_refr.h

lv_api_map_v9_1.h

lv_obj_pos.h

lv_obj.h

lv_api_map_v8.h

lv_obj_draw.h

lv_obj_event.h

lv_obj_property.h

lv_obj_style_gen.h

lv_observer.h

lv_obj_tree.h