Events(事件)

查看原文

Events are triggered in LVGL when something happens which might be interesting to the user, e.g. when an object

  • is clicked

  • is scrolled

  • has its value changed

  • is redrawn, etc.

当发生用户可能感兴趣的事情时,LVGL 中会触发事件,例如当一个对象

  • 被点击

  • 滚动

  • 数值被改变

  • 重绘等。

Add events to the object

查看原文

The user can assign callback functions to an object to see its events. In practice, it looks like this:

用户可以为对象分配回调函数以查看其事件。在实践中,它看起来像这样:

lv_obj_t * btn = lv_btn_create(lv_scr_act());
lv_obj_add_event_cb(btn, my_event_cb, LV_EVENT_CLICKED, NULL);   /*Assign an event callback*/

...

static void my_event_cb(lv_event_t * event)
{
    printf("Clicked\n");
}
查看原文

In the example LV_EVENT_CLICKED means that only the click event will call my_event_cb. See the list of event codes for all the options. LV_EVENT_ALL can be used to receive all the events.

The last parameter of lv_obj_add_event_cb is a pointer to any custom data that will be available in the event. It will be described later in more detail.

More events can be added to an object, like this:

在示例中 LV_EVENT_CLICKED 意味着只有当对象发生点击事件时,就会触发事件从而进入事件处理回调函数 my_event_cb 。有关所有选项,请参阅事件代码列表LV_EVENT_ALL 可用于接收所有事件。

lv_obj_add_event_cb 的最后一个参数是指向事件中可用的任何自定义数据的指针。稍后将更详细地描述。

可以向一个对象添加更多事件,如下所示:

lv_obj_add_event_cb(obj, my_event_cb_1, LV_EVENT_CLICKED, NULL);
lv_obj_add_event_cb(obj, my_event_cb_2, LV_EVENT_PRESSED, NULL);
lv_obj_add_event_cb(obj, my_event_cb_3, LV_EVENT_ALL, NULL);		/*No filtering, receive all events*/
查看原文

Even the same event callback can be used on an object with different user_data. For example:

如果传入的用户数据不一样,一个对象可以绑定同一个事件回调函数多次。例如:

lv_obj_add_event_cb(obj, increment_on_click, LV_EVENT_CLICKED, &num1);
lv_obj_add_event_cb(obj, increment_on_click, LV_EVENT_CLICKED, &num2);
查看原文

The events will be called in the order as they were added.

More objects can use the same event callback.

这些事件将按照添加的顺序被调用。

更多的对象可以使用相同的 事件回调

Remove event(s) from an object(从对象中删除事件)

查看原文

Events can be removed from an object with the lv_obj_remove_event_cb(obj, event_cb) function or lv_obj_remove_event_dsc(obj, event_dsc). event_dsc is a pointer returned by lv_obj_add_event_cb.

可以使用 lv_obj_remove_event_cb(obj, event_cb) 函数或 lv_obj_remove_event_dsc(obj, event_dsc) 从对象中删除事件。 event_dsc 是一个由 lv_obj_add_event_cb 返回的指针。

Event codes

查看原文

The event codes can be grouped into these categories:

  • Input device events

  • Drawing events

  • Other events

  • Special events

  • Custom events

All objects (such as Buttons/Labels/Sliders etc.) regardless their type receive the Input device, Drawing and Other events.

However the Special events are specific to a particular widget type. See the widgets' documentation to learn when they are sent,

Custom events are added by the user and therefore these are never sent by LVGL.

The following event codes exist:

事件代码可以分为以下几类:

  • 输入设备事件(Input device events)

  • 绘图事件(Drawing events)

  • 其他事件(Special events)

  • 特殊事件(Other events)

  • 自定义事件(Custom events)

请查阅源码:lvgl/src/core/lv_event.h (lv_event_code_t)

所有对象(例如按钮/标签/滑块等),无论其类型如何,都会接收 Input deviceDrawingOther 事件。

然而,特殊事件 特定于特定的小部件类型。查看 widgets' 文档 了解何时发送,

自定义事件 由用户添加,因此这些事件永远不会由 LVGL 发送。

存在以下事件代码:

Input device events(输入设备事件)

查看原文

  • LV_EVENT_PRESSED The object has been pressed

  • LV_EVENT_PRESSING The object is being pressed (called continuously while pressing)

  • LV_EVENT_PRESS_LOST The object is still being pressed but slid cursor/finger off of the object

  • LV_EVENT_SHORT_CLICKED The object was pressed for a short period of time, then released it. Not called if scrolled.

  • LV_EVENT_LONG_PRESSED Object has been pressed for at least the long_press_time specified in the input device driver. Not called if scrolled.

  • LV_EVENT_LONG_PRESSED_REPEAT Called after long_press_time in every long_press_repeat_time ms. Not called if scrolled.

  • LV_EVENT_CLICKED Called on release if the object did not scroll (regardless of long press)

  • LV_EVENT_RELEASED Called in every case when the object has been released

  • LV_EVENT_SCROLL_BEGIN Scrolling begins. The event paramter is NULL or an lv_anim_t * with the scroll animation descriptor to modify if required.

  • LV_EVENT_SCROLL_END Scrolling ends.

  • LV_EVENT_SCROLL The object was scrolled

  • LV_EVENT_GESTURE A gesture is detected. Get the gesture with lv_indev_get_gesture_dir(lv_indev_get_act());

  • LV_EVENT_KEY A key is sent to the object. Get the key with lv_indev_get_key(lv_indev_get_act());

  • LV_EVENT_FOCUSED The object is focused

  • LV_EVENT_DEFOCUSED The object is defocused

  • LV_EVENT_LEAVE The object is defocused but still selected

  • LV_EVENT_HIT_TEST Perform advanced hit-testing. Use lv_hit_test_info_t * a = lv_event_get_hit_test_info(e) and check if a->point can click the object or not. If not set a->res = false

  • LV_EVENT_PRESSED 对象已被按下

  • LV_EVENT_PRESSING 对象被按下(按下时连续调用)

  • LV_EVENT_PRESS_LOST 对象仍被按下,但光标/手指已滑离对象

  • LV_EVENT_SHORT_CLICKED 对象被按下一小段时间,然后释放它。如果滚动则不会调用。

  • LV_EVENT_LONG_PRESSED 对象已按下输入设备驱动程序中指定的至少 long_press_time。如果滚动则不会调用。

  • LV_EVENT_LONG_PRESSED_REPEAT 在每个 long_press_repeat_time 毫秒的 long_press_time 之后调用。如果滚动则不会调用。

  • LV_EVENT_CLICKED 如果对象没有滚动,则在释放时调用(无论是否长按)

  • LV_EVENT_RELEASED 在对象被释放后的每种情况下调用

  • LV_EVENT_SCROLL_BEGIN 开始滚动。事件参数是 NULLlv_anim_t *,如果需要,可以修改滚动动画描述符。

  • LV_EVENT_SCROLL_END 滚动结束。

  • LV_EVENT_SCROLL 对象被滚动

  • LV_EVENT_GESTURE 检测到手势。使用 lv_indev_get_gesture_dir(lv_indev_get_act()); 获取手势

  • LV_EVENT_KEY 一个密钥被发送到对象。使用 lv_indev_get_key(lv_indev_get_act()); 获取密钥

  • LV_EVENT_FOCUSED 对象被聚焦

  • LV_EVENT_DEFOCUSED 对象散焦

  • LV_EVENT_LEAVE 对象散焦但仍被选中

  • LV_EVENT_HIT_TEST 执行高级命中测试。使用 lv_hit_test_info_t * a = lv_event_get_hit_test_info(e) 并检查 a->point 是否可以点击对象。如果没有则 a->res = false

Drawing events(绘图事件)

查看原文

  • LV_EVENT_COVER_CHECK Check if the object fully covers an area. The event parameter is lv_cover_check_info_t *.

  • LV_EVENT_REFR_EXT_DRAW_SIZE Get the required extra draw area around the object (e.g. for shadow). The event parameter is lv_coord_t * to store the size. Overwrite it only with a larger value.

  • LV_EVENT_DRAW_MAIN_BEGIN Starting the main drawing phase.

  • LV_EVENT_DRAW_MAIN Perform the main drawing

  • LV_EVENT_DRAW_MAIN_END Finishing the main drawing phase

  • LV_EVENT_DRAW_POST_BEGIN Starting the post draw phase (when all children are drawn)

  • LV_EVENT_DRAW_POST Perform the post draw phase (when all children are drawn)

  • LV_EVENT_DRAW_POST_END Finishing the post draw phase (when all children are drawn)

  • LV_EVENT_DRAW_PART_BEGIN Starting to draw a part. The event parameter is lv_obj_draw_dsc_t *. Learn more here.

  • LV_EVENT_DRAW_PART_END Finishing to draw a part. The event parameter is lv_obj_draw_dsc_t *. Learn more here.

  • LV_EVENT_COVER_CHECK 检查对象是否完全覆盖一个区域。事件参数是lv_cover_check_info_t *

  • LV_EVENT_REFR_EXT_DRAW_SIZE 获取对象周围所需的额外绘制区域(例如用于阴影)。事件参数是 lv_coord_t * 来存储大小。仅用更大的值覆盖它。

  • LV_EVENT_DRAW_MAIN_BEGIN 开始主绘图阶段。

  • LV_EVENT_DRAW_MAIN 执行主绘图

  • LV_EVENT_DRAW_MAIN_END 完成主绘制阶段

  • LV_EVENT_DRAW_POST_BEGIN 开始后期绘制阶段(当所有孩子都被绘制时)

  • LV_EVENT_DRAW_POST 执行后期绘制阶段(当所有孩子都被绘制时)

  • LV_EVENT_DRAW_POST_END 完成后期绘制阶段(当所有孩子都被绘制时)

  • LV_EVENT_DRAW_PART_BEGIN 开始绘制零件。事件参数是lv_obj_draw_dsc_t *。了解更多 此处

  • LV_EVENT_DRAW_PART_END 完成绘制零件。事件参数是lv_obj_draw_dsc_t *。了解更多 此处

Other events(其他事件)

查看原文

  • LV_EVENT_DELETE Object is being deleted

  • LV_EVENT_CHILD_CHANGED Child was removed/added

  • LV_EVENT_SIZE_CHANGED Object coordinates/size have changed

  • LV_EVENT_STYLE_CHANGED Object's style has changed

  • LV_EVENT_BASE_DIR_CHANGED The base dir has changed

  • LV_EVENT_GET_SELF_SIZE Get the internal size of a widget

  • LV_EVENT_DELETE 对象正在被删除

  • LV_EVENT_CHILD_CHANGED 孩子被移除/添加

  • LV_EVENT_SIZE_CHANGED 对象坐标/大小已更改

  • LV_EVENT_STYLE_CHANGED 对象的样式已更改

  • LV_EVENT_BASE_DIR_CHANGED 基础目录已经改变

  • LV_EVENT_GET_SELF_SIZE 获取小部件的内部尺寸

Special events(特殊事件)

查看原文

  • LV_EVENT_VALUE_CHANGED The object's value has changed (i.e. slider moved)

  • LV_EVENT_INSERT A text is being inserted to the object. The event data is char * being inserted.

  • LV_EVENT_REFRESH Notify the object to refresh something on it (for the user)

  • LV_EVENT_READY A process has finished

  • LV_EVENT_CANCEL A process has been canceled

  • LV_EVENT_VALUE_CHANGED 对象的值已更改(即滑块移动)

  • LV_EVENT_INSERT 正在向对象插入文本。事件数据是插入的char *

  • LV_EVENT_REFRESH 通知对象刷新其上的某些内容(对于用户)

  • LV_EVENT_READY 一个过程已经完成

  • LV_EVENT_CANCEL 一个过程被取消

Custom events(自定义事件)

查看原文

Any custom event codes can be registered by uint32_t MY_EVENT_1 = lv_event_register_id();

And can be sent to any object with lv_event_send(obj, MY_EVENT_1, &some_data)

任何自定义事件代码都可以通过 uint32_t MY_EVENT_1 = lv_event_register_id(); 注册

并且可以使用 lv_event_send(obj, MY_EVENT_1, &some_data) 发送到任何对象

Sending events(发送事件)

查看原文

To manually send events to an object, use lv_event_send(obj, <EVENT_CODE> &some_data).

For example, this can be used to manually close a message box by simulating a button press (although there are simpler ways to do this):

要手动向对象发送事件,请使用 lv_event_send(obj, <EVENT_CODE> &some_data)

例如,这可用于通过模拟按钮按下来手动关闭消息框(尽管有更简单的方法可以做到这一点):

/*Simulate the press of the first button (indexes start from zero)*/
uint32_t btn_id = 0;
lv_event_send(mbox, LV_EVENT_VALUE_CHANGED, &btn_id);

Refresh event(刷新事件)

查看原文

LV_EVENT_REFRESH is special event because it's designed to be used by the user to notify an object to refresh itself. Some examples:

  • notify a label to refresh its text according to one or more variables (e.g. current time)

  • refresh a label when the language changes

  • enable a button if some conditions are met (e.g. the correct PIN is entered)

  • add/remove styles to/from an object if a limit is exceeded, etc

LV_EVENT_REFRESH 是一个特殊事件,因为它被设计为用户使用它来通知对象刷新自身。一些例子:

  • 通知标签根据一个或多个变量(例如当前时间)刷新其文本

  • 当语言改变时刷新标签

  • 如果满足某些条件(例如输入正确的 PIN),则启用按钮

  • 如果超出限制,则向/从对象添加/删除样式等

Fields of lv_event_t(lv_event_t 的字段)

查看原文

lv_event_t is the only parameter passed to event callback and it contains all the data about the event. The following values can be gotten from it:

  • lv_event_get_code(e) get the event code

  • lv_event_get_target(e) get the object to which the event is sent

  • lv_event_get_original_target(e) get the object to which the event is sent originally sent (different from lv_event_get_target if event bubbling is enabled)

  • lv_event_get_user_data(e) get the pointer passed as the last parameter of lv_obj_add_event_cb.

  • lv_event_get_param(e) get the parameter passed as the last parameter of lv_event_send

lv_event_t 是传递给事件回调的唯一参数,它包含有关事件的所有数据。可以从中获得以下值:

  • lv_event_get_code(e) 获取触发的事件代码

  • lv_event_get_target(e) 获取事件发送到(关联)的对象

  • lv_event_get_original_target(e) 获取事件最初发送到的对象(与 lv_event_get_target 不同,如果 event bubbling 被启用)

  • lv_event_get_user_data(e) 获取作为 lv_obj_add_event_cb 的最后一个参数传递的指针。

  • lv_event_get_param(e) 获取作为 lv_event_send 的最后一个参数传递的参数

Event bubbling(事件冒泡)

查看原文

If lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE) is enabled all events will be sent to the object's parent too. If the parent also has LV_OBJ_FLAG_EVENT_BUBBLE enabled the event will be sent to its parent too, and so on.

The target parameter of the event is always the current target object, not the original object. To get the original target call lv_event_get_original_target(e) in the event handler.

如果启用了 lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE),所有事件也将发送到对象的父级。如果父级也启用了LV_OBJ_FLAG_EVENT_BUBBLE,则事件也将发送到其父级,依此类推。

事件的 target 参数始终是当前目标对象,而不是原始对象。在事件处理程序中获取原始目标调用 lv_event_get_original_target(e)

Examples

Button click event

C code  

 GitHub
#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_SWITCH

static void event_cb(lv_event_t * e)
{
    LV_LOG_USER("Clicked");

    static uint32_t cnt = 1;
    lv_obj_t * btn = lv_event_get_target(e);
    lv_obj_t * label = lv_obj_get_child(btn, 0);
    lv_label_set_text_fmt(label, "%"LV_PRIu32, cnt);
    cnt++;
}

/**
 * Add click event to a button
 */
void lv_example_event_1(void)
{
    lv_obj_t * btn = lv_btn_create(lv_scr_act());
    lv_obj_set_size(btn, 100, 50);
    lv_obj_center(btn);
    lv_obj_add_event_cb(btn, event_cb, LV_EVENT_CLICKED, NULL);

    lv_obj_t * label = lv_label_create(btn);
    lv_label_set_text(label, "Click me!");
    lv_obj_center(label);
}

#endif

MicroPython code  

 GitHub Simulator
class Event_1():
    def __init__(self):
        self.cnt = 1
        #
        # Add click event to a button
        #

        btn = lv.btn(lv.scr_act())
        btn.set_size(100, 50)
        btn.center()
        btn.add_event_cb(self.event_cb, lv.EVENT.CLICKED, None)
        
        label = lv.label(btn)
        label.set_text("Click me!")
        label.center()

    def event_cb(self,e):
        print("Clicked")
            
        btn = e.get_target()
        label = btn.get_child(0)
        label.set_text(str(self.cnt))
        self.cnt += 1

evt1 = Event_1()

Handle multiple events

C code  

 GitHub
#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_SWITCH

static void event_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * label = lv_event_get_user_data(e);

    switch(code) {
    case LV_EVENT_PRESSED:
        lv_label_set_text(label, "The last button event:\nLV_EVENT_PRESSED");
        break;
    case LV_EVENT_CLICKED:
        lv_label_set_text(label, "The last button event:\nLV_EVENT_CLICKED");
        break;
    case LV_EVENT_LONG_PRESSED:
        lv_label_set_text(label, "The last button event:\nLV_EVENT_LONG_PRESSED");
        break;
    case LV_EVENT_LONG_PRESSED_REPEAT:
        lv_label_set_text(label, "The last button event:\nLV_EVENT_LONG_PRESSED_REPEAT");
        break;
    default:
        break;
    }
}

/**
 * Handle multiple events
 */
void lv_example_event_2(void)
{
    lv_obj_t * btn = lv_btn_create(lv_scr_act());
    lv_obj_set_size(btn, 100, 50);
    lv_obj_center(btn);

    lv_obj_t * btn_label = lv_label_create(btn);
    lv_label_set_text(btn_label, "Click me!");
    lv_obj_center(btn_label);

    lv_obj_t * info_label = lv_label_create(lv_scr_act());
    lv_label_set_text(info_label, "The last button event:\nNone");

    lv_obj_add_event_cb(btn, event_cb, LV_EVENT_ALL, info_label);
}

#endif

MicroPython code  

 GitHub Simulator
def event_cb(e,label):
    code = e.get_code()
    if code == lv.EVENT.PRESSED:
        label.set_text("The last button event:\nLV_EVENT_PRESSED")
    elif code == lv.EVENT.CLICKED:
        label.set_text("The last button event:\nLV_EVENT_CLICKED")
    elif code ==  lv.EVENT.LONG_PRESSED:
        label.set_text("The last button event:\nLV_EVENT_LONG_PRESSED")
    elif code == lv.EVENT.LONG_PRESSED_REPEAT:
        label.set_text("The last button event:\nLV_EVENT_LONG_PRESSED_REPEAT")        
btn = lv.btn(lv.scr_act())
btn.set_size(100, 50)
btn.center()

btn_label = lv.label(btn)
btn_label.set_text("Click me!")
btn_label.center()

info_label = lv.label(lv.scr_act())
info_label.set_text("The last button event:\nNone")

btn.add_event_cb(lambda e: event_cb(e,info_label), lv.EVENT.ALL, None)

Event bubbling

C code  

 GitHub
#include "../lv_examples.h"
#if LV_BUILD_EXAMPLES && LV_USE_FLEX

static void event_cb(lv_event_t * e)
{
    /*The original target of the event. Can be the buttons or the container*/
    lv_obj_t * target = lv_event_get_target(e);

    /*The current target is always the container as the event is added to it*/
    lv_obj_t * cont = lv_event_get_current_target(e);

    /*If container was clicked do nothing*/
    if(target == cont) return;

    /*Make the clicked buttons red*/
    lv_obj_set_style_bg_color(target, lv_palette_main(LV_PALETTE_RED), 0);
}

/**
 * Demonstrate event bubbling
 */
void lv_example_event_3(void)
{

    lv_obj_t * cont = lv_obj_create(lv_scr_act());
    lv_obj_set_size(cont, 290, 200);
    lv_obj_center(cont);
    lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_ROW_WRAP);

    uint32_t i;
    for(i = 0; i < 30; i++) {
        lv_obj_t * btn = lv_btn_create(cont);
        lv_obj_set_size(btn, 80, 50);
        lv_obj_add_flag(btn, LV_OBJ_FLAG_EVENT_BUBBLE);

        lv_obj_t * label = lv_label_create(btn);
        lv_label_set_text_fmt(label, "%"LV_PRIu32, i);
        lv_obj_center(label);
    }

    lv_obj_add_event_cb(cont, event_cb, LV_EVENT_CLICKED, NULL);
}

#endif

MicroPython code  

 GitHub Simulator
def event_cb(e):

    # The original target of the event. Can be the buttons or the container
    target = e.get_target()
    # print(type(target))

    # If container was clicked do nothing
    if type(target) != type(lv.btn()):
        return

    # Make the clicked buttons red
    target.set_style_bg_color(lv.palette_main(lv.PALETTE.RED), 0)

#
# Demonstrate event bubbling
#

cont = lv.obj(lv.scr_act())
cont.set_size(320, 200)
cont.center()
cont.set_flex_flow(lv.FLEX_FLOW.ROW_WRAP)

for i in range(30):
    btn = lv.btn(cont)
    btn.set_size(80, 50)
    btn.add_flag(lv.obj.FLAG.EVENT_BUBBLE)

    label = lv.label(btn)
    label.set_text(str(i))
    label.center()
    cont.add_event_cb(event_cb, lv.EVENT.CLICKED, None)