[English]

Quick overview(快速概览)

显示原文

Here you can learn the most important things about LVGL. You should read this first to get a general impression and read the detailed Porting(移植) and Overview(概述) sections after that.


在这里您可以了解有关 LVGL 的最重要的事情。 您应该先阅读这部分内容以获得大致印象,然后再阅读详细的 porting(移植)overview(概述) 部分。

Get started in a simulator(从模拟器开始)

显示原文

Instead of porting LVGL to embedded hardware straight away, it's highly recommended to get started in a simulator first.

LVGL is ported to many IDEs to be sure you will find your favorite one. Go to the Simulator on PC(PC端模拟器) section to get ready-to-use projects that can be run on your PC. This way you can save the time of porting for now and get some experience with LVGL immediately.


强烈建议您先在lvgl模拟器上开始学习实验,而不是立即将 LVGL 移植到嵌入式硬件。

LVGL 被移植到许多 IDE 中,以确保您能找到自己最喜欢的那个。转到 simulator(模拟器) 部分以获取可以在您的 PC 上运行的现成项目。通过这种方式,您现在可以节省移植时间,并立即获得一些使用 LVGL 的经验。(这是非常有用的!)

Add LVGL into your project(将 LVGL 添加到您的项目中)

显示原文

If you would rather try LVGL on your own project follow these steps:

  • Download or clone the library from GitHub with git clone https://github.com/lvgl/lvgl.git.

  • Copy the lvgl folder into your project.

  • Copy lvgl/lv_conf_template.h as lv_conf.h next to the lvgl folder, change the first #if 0 to 1 to enable the file's content and set the LV_COLOR_DEPTH defines.

  • Include lvgl/lvgl.h in files where you need to use LVGL related functions.

  • Call lv_init()

  • Call lv_tick_inc(x) every x milliseconds in a Timer or Task (x should be between 1 and 10). It is required for the internal timing of LVGL. Alternatively, register a tick_get_cb with lv_tick_set_cb() so that LVGL can retrieve the current time directly.

  • Create a display.


如果您想在自己的项目中尝试 LVGL,请按照以下步骤操作:

  • 从 GitHub 下载 或使用git命令 git clone https://github.com/lvgl/lvgl.git 从GitHub克隆库。

  • lvgl 文件夹复制到您的项目中。

  • lvgl/lv_conf_template.h 复制为 lv_conf.h 并放在 lvgl 文件夹旁边,将其第一个的 #if 0 更改为 1 以启用该文件的内容并修改设置 LV_COLOR_DEPTH 定义。

  • 在需要使用 LVGL 相关函数的文件中包含 lvgl/lvgl.h

  • 调用 lv_init() (初始化lvgl库)

  • 在定时器或任务中每 x 毫秒调用一次 lv_tick_inc(x) (x 应该在 1 到 10 之间)。 这是 LVGL 的内部计时所必需的。或者,使用 lv_tick_set_cb() 注册一个 tick_get_cb ,以便LVGL可以直接检索当前时间。

  • 创建一个显示器。

lv_display_t *display = lv_display_create(MY_DISP_HOR_RES, MY_DISP_VER_RES);
显示原文
  • Create a draw buffer: LVGL supports multiple buffering methods. Here you

can see how to set up partial buffering (that is render the screen and the changed areas in a smaller buffer). The buffer size can be set freely but 1/10 screen size is a good starting point.


  • 创建一个绘制缓冲区:LVGL支持多种缓冲方法。在这里,你可以看到如何设置局部缓冲(即在一个较小的缓冲区中渲染屏幕和已更改的区域)。 缓冲区的大小可以自由设置,但以屏幕大小的 1/10 作为起点是一个不错的选择。

/*Declare a buffer for 1/10 screen size*/
#define BYTE_PER_PIXEL (LV_COLOR_FORMAT_GET_SIZE(LV_COLOR_FORMAT_RGB565)) /*will be 2 for RGB565 */
static uint8_t buf1[MY_DISP_HOR_RES * MY_DISP_VER_RES / 10 * BYTE_PER_PIXEL];
lv_display_set_buffers(display, buf1, NULL, sizeof(buf1), LV_DISPLAY_RENDER_MODE_PARTIAL);  /*Initialize the display buffer.*/
显示原文
  • Implement and register a function which can copy the rendered image to an area of your display:


  • 实现并注册一个能够将渲染后的图像复制到你的显示器的某个区域的函数:

lv_display_set_flush_cb(display, my_disp_flush);

void my_disp_flush(lv_display_t * disp, const lv_area_t * area, lv_color_t * color_p)
{
    int32_t x, y;
    /*It's a very slow but simple implementation.
     *`set_pixel` needs to be written by you to a set pixel on the screen*/
    for(y = area->y1; y <= area->y2; y++) {
        for(x = area->x1; x <= area->x2; x++) {
            set_pixel(x, y, *color_p);
            color_p++;
        }
    }

    lv_display_flush_ready(disp);         /* Indicate you are ready with the flushing*/
}
显示原文
  • Implement and register a function which can read an input device. E.g. for a touchpad:


  • 实现并注册一个可以读取输入设备的函数。例如。对于触摸板:

lv_indev_t * indev = lv_indev_create();           /*Create an input device*/
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);  /*Touch pad is a pointer-like device*/
lv_ondev_set_read_cb(indev, my_touchpad_read);    /*Set your driver function*/

void my_touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
    /*`touchpad_is_pressed` and `touchpad_get_xy` needs to be implemented by you*/
    if(touchpad_is_pressed()) {
      data->state = LV_INDEV_STATE_PRESSED;
      touchpad_get_xy(&data->point.x, &data->point.y);
    } else {
      data->state = LV_INDEV_STATE_RELEASED;
    }

}
显示原文
  • Call lv_timer_handler() periodically every few milliseconds in the main while(1) loop or in an operating system task. It will redraw the screen if required, handle input devices, animation etc.

For a more detailed guide go to the Porting(移植) section.


在主函数 while(1) 循环中或操作系统任务中每隔几毫秒定期调用 lv_timer_handler() 。 如果需要,它将重绘屏幕,处理输入设备、动画等。

有关更详细的指南,请转到 porting(移植) 部分。

Learn the basics(学习基础知识)

Widgets(控件)

显示原文

The graphical elements like Buttons, Labels, Sliders, Charts etc. are called objects or widgets. Go to Widgets(控件) to see the full list of available widgets.

Every object has a parent object where it is created. For example, if a label is created on a button, the button is the parent of label.

The child object moves with the parent and if the parent is deleted the children will be deleted too.

Children can be visible only within their parent's bounding area. In other words, the parts of the children outside the parent are clipped.

A Screen is the "root" parent. You can have any number of screens.

To get the current screen call lv_screen_active(), and to load a screen use lv_screen_load(scr1).

You can create a new object with lv_<type>_create(parent). It will return an lv_obj_t * variable that can be used as a reference to the object to set its parameters.

For example:

lv_obj_t * slider1 = lv_slider_create(lv_screen_active());

To set some basic attributes lv_obj_set_<parameter_name>(obj, <value>) functions can be used. For example:

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

Along with the basic attributes, widgets can have type specific parameters which are set by lv_<widget_type>_set_<parameter_name>(obj, <value>) functions. For example:

lv_slider_set_value(slider1, 70, LV_ANIM_ON);

To see the full API visit the documentation of the widgets or the related header file (e.g. lvgl/src/widgets/slider/lv_slider.h).


按钮、标签、滑块、图表等图形元素称为对象或小部件。转到 widgets(控件) 以查看可用小部件的完整列表。

每个对象都有一个创建它的父对象。例如,如果一个标签创建在一个按钮上,那么这个按钮就是标签的父对象。

子对象与父对象一起移动,如果删除父对象,子对象也将被删除。

子对象只能在其父项上可见。换句话说,子对象在父对象外部的部分会被裁剪。

Screen 是“根”父级。您可以拥有任意数量的屏幕。

要获取当前屏幕,可以调用 lv_screen_active(),并使用 lv_screen_load(scr1) 加载屏幕。

您可以使用 lv_<type>_create(parent) 创建一个新对象。它将返回一个 lv_obj_t * 类型的变量,这个变量可以作为对该对象的引用以设置其参数。

For example(例如):

lv_obj_t * slider1 = lv_slider_create(lv_screen_active());

要设置一些基本属性,可以使用 lv_obj_set_<parameter_name>(obj, <value>) 函数。例如:

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

除了基本属性外,小部件还可以具有特定类型的参数,这些参数通过 lv_<widget_type>_set_<parameter_name>(obj, <value>) 函数进行设置。例如:

lv_slider_set_value(slider1, 70, LV_ANIM_ON);

要查看完整的 API,请访问小部件的文档或相关的头文件(例如 lvgl/src/widgets/slider/lv_slider.h)。

Events(事件)

显示原文

Events are used to inform the user that something has happened with an object. You can assign one or more callbacks to an object which will be called if the object is clicked, released, dragged, being deleted, etc.

A callback is assigned like this:

lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL); /*Assign a callback to the button*/

...

void 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 any event.

From lv_event_t * e the current event code can be retrieved with:

lv_event_code_t code = lv_event_get_code(e);

The object 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.


事件用于通知用户某个对象发生了某些事情。 您可以为一个对象分配一个或多个回调函数,如果该对象被单击、释放、拖动、删除等情况发生时,这些回调函数将被调用。

回调函数的分配方式如下:

lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL); /*为按钮分配一个回调函数*/

...

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

LV_EVENT_CLICKED 可以代替 LV_EVENT_ALL ,以便在任何事情发生时调用回调函数。

lv_event_t * e 中,可以使用以下方式获取当前事件代码:

lv_event_code_t code = lv_event_get_code(e);

触发事件的对象可以通过以下方式获取:

lv_obj_t * obj = lv_event_get_target(e);

要了解事件的所有功能,请转到 Events(事件) 部分。

Parts(部分)

显示原文

Widgets might be built from one or more parts. For example, a button has only one part called LV_PART_MAIN. However, a lv_slider.h 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 widgets' documentation to learn which parts each uses.


部件可能由一个或多个 部分 组成。例如,一个按钮只有一个名为 LV_PART_MAIN 的部分。但是,一个 lv_slider(滑块) 具有 LV_PART_MAINLV_PART_INDICATORLV_PART_KNOB

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

阅读小部件的文档,了解每个小部件使用的部分。

States(状态)

显示原文

LVGL objects can be in a combination of the following states:

For example, if you press an object 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 focus remains active.

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

To manually add or remove states use:


LVGL 对象可以处于以下状态的组合:

例如,如果你按下一个对象,它会自动进入 LV_STATE_FOCUSEDLV_STATE_PRESSED 状态,当你释放它时, LV_STATE_PRESSED 状态将被移除,而焦点任然保持活动状态。

要检查对象是否处于给定状态,请使用 lv_obj_has_state(obj, LV_STATE_...)。如果对象当时处于该状态,它将返回 true

要手动添加或删除状态,请使用下面的函数:

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

Styles(样式)

显示原文

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

Styles are represented with lv_style_t variables. Only their pointer is saved in the objects so they need to be defined as static or global. 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:


一个样式实例包含背景颜色、边框宽度、字体等属性,用于描述对象的外观。

样式用 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))
显示原文

See the full list of properties here Properties(属性).

Styles are assigned using the ORed combination of an object's part and state. For example to use this style on the slider's indicator when the slider is pressed:


在此处查看属性的完整列表 Properties(属性)

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

lv_obj_add_style(slider1, &style1, LV_PART_INDICATOR | LV_STATE_PRESSED);
显示原文

If the part is LV_PART_MAIN it can be omitted:


如果 partLV_PART_MAIN ,则可以省略它:

lv_obj_add_style(btn1, &style1, LV_STATE_PRESSED); /*Equal to LV_PART_MAIN | LV_STATE_PRESSED*/
显示原文

Similarly, LV_STATE_DEFAULT can be omitted too:


类似地, LV_STATE_DEFAULT 也可以省略:

lv_obj_add_style(slider1, &style1, LV_PART_INDICATOR); /*Equal to LV_PART_INDICATOR | LV_STATE_DEFAULT*/
显示原文

For LV_STATE_DEFAULT and LV_PART_MAIN simply write 0:


对于 LV_STATE_DEFAULTLV_PART_MAIN 只需写下 0:

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

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


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

lv_obj_add_style(btn1, &style_btn, 0);
lv_obj_add_style(btn1, &style1_btn_red, 0);
显示原文

If a property is not set on 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 (typically the text-related ones) can be inherited. This means if a property is not set in an object it will be searched for in its parents too. 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 objects. This creates a style which resides inside the object and is used only by the object:


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

一些属性(通常是与文本相关的属性)可以被继承。这意味着如果一个对象中未设置某个属性,它也会在它的父对象进行查找。 例如,您可以在屏幕的样式中设置一次字体,该屏幕上的所有文本都将默认继承它。

也可以向对象添加局部样式属性。这将创建一个驻留在对象内部且仅由该对象使用的样式:

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 the Styles(风格样式) section.


要了解样式的所有功能,请参阅 Styles(风格样式) 部分。

Themes(主题)

显示原文

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

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


主题是对象的默认样式。创建对象时,将自动应用来自主题的样式。

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

Examples

[English]

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

MicroPython

显示原文

Learn more about MicroPython.


了解有关 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)