2-8-1+2_基础对象的事件(events)

2-8-1+2_基础对象的事件(events)

知识部分

原文档

实践部分

Add events to a widget(添加事件到对象)添加事件

Sending events(发送事件)

Remove event(s) from widgets(从对象中删除事件) Refresh event(刷新事件)

Event codes(事件代码)

Input device events(输入设备事件) Drawing events(绘图事件)

Special events(特殊事件) Other events(其他事件) Display events(展示时间) Custom events(自定义事件)

Fields of lv_event_t(lv_event_t 的字段)与事件回调函数事件与对象之间的关系

Event bubbling(事件冒泡)

知识部分

原文档

https://lvgl.100ask.net/9.1/overview/event.html

当发⽣⽤⼾可能感兴趣的事情时,LVGL 中会触发事件并作出相应的处理(反馈),例如当

⼀个对象:

被点击滚动

数值改变重绘等等。。。

实践部分

Add events to a widget(添加事件到对象)

显示原文

用户可以为对象指定回调函数以查看其事件。 实际操作是这样的:

lv_obj_t * btn = lv_button_create(lv_screen_active()); lv_obj_add_event_cb(btn, my_event_cb, LV_EVENT_CLICKED, NULL); /*

分配一个事件回调*/

...

static void my_event_cb(lv_event_t * event)

{

printf("Clicked\n");

}

在示例中 LV_EVENT_CLICKED 意味着只有点击事件会调用 my_event_cb 。查看 事件代码列表 以获取所有选项。 LV_EVENT_ALL 可用于接收所有事件。

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

可以向对象添加更多事件,像这样:

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); l

v_obj_add_event_cb(obj, my_event_cb_3, LV_EVENT_ALL, NULL);

/*无过滤,接收所有事件*/

甚至相同的事件回调也可以在具有不同“user_data”的对象上使用。例如:

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);

事件将按其被添加的顺序调用。

其他对象可以使用相同的 事件回调。

以完全相同的方式,事件可以附加到输入设备和显示器上,像这样:

lv_display_add_event_cb(disp, event_cb, LV_EVENT_RESOLUTION_CHANGED, NULL);

lv_indev_add_event_cb(indev, event_cb, LV_EVENT_CLICKED, NULL);

添加事件

lv_obj_t * btn = lv_button_create(lv_screen_active());

lv_obj_add_event_cb(btn, my_event_cb, LV_EVENT_CLICKED, NULL);

/*分配一个事件回调*/

...

static void my_event_cb(lv_event_t * event)

{

printf("Clicked\n");

}

在示例中 LV_EVENT_CLICKED 意味着只有点击事件会调用 my_event_cb 。查看 事件代码列表 以获取所有选项。 LV_EVENT_ALL 可用于接收所有事件。

Demo

void lesson_2_8_1(void)

{

/* 创建基础部件(对象) */

lv_obj_t * obj = lv_obj_create(lv_screen_active());

/* 创建label部件(对象) */

lv_obj_t * label = lv_label_create(lv_screen_active()); lv_label_set_text(label, "test"); // 设置label展示的文字 lv_obj_center(label); // 将对象与其父对象的中心对齐,这

里的父对象是屏幕:lv_screen_active()

// 为obj1添加事件回调函数,所有的事件类型都能触发该回调函数

lv_obj_add_event_cb(obj, my_event_cb, LV_EVENT_ALL, label);

}

Sending events(发送事件)

lv_result_t lv_obj_send_event(lv_obj_t *obj, lv_event_code_t event_code, void *param)

/*
    向对象发送事件

    参数:

    obj -- 对象的指针

    event_code -- 来自 lv_event_t 的事件类型

    param -- 根据控件类型和事件而定的任意数据。(通常为NULL)

    返回:

    LV_RESULT_OK: 对象未在事件中被删; LV_RESULT_INVALID: 对象在事件代码中被删除
*/

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

uint32_t lv_obj_remove_event_cb_with_user_data(lv_obj_t *obj, lv_event_cb_t event_cb, void *user_data)

/*移除一个带有user_data的事件回调函数参数:

    参数:

    obj -- 指向一个对象的指针

    event_cb -- 要移除的事件的event_cb user_data -- 用户数据

    返回:

    移除的事件数量

*/

bool lv_obj_remove_event_dsc(lv_obj_t *obj, lv_event_dsc_t *dsc)

//event_dsc 是 lv_obj_add_event_cb 返回的指针

Refresh event(刷新事件)

显示原文

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

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

当语言发生变化时刷新标签

如果满足一些条件(比如输入了正确的PIN码),则启用一个按钮当超出限制时,为对象添加/移除样式,等等

Event codes(事件代码)

显示原文

事件代码可以分为以下类别:- 输入设备事件 - 绘图事件 - 其他事件 - 特殊事件 - 自定义事件所有对象(如按钮/标签/滑块等)无论其类型,都会接收 输入设备、 绘图 和 其他 事件。

然而, 特殊事件 是特定于特定部件类型的。请参阅 widgets' documentation 以了解它们何时被发送。

自定义事件 是用户添加的,并且永远不会被LVGL发送。存在以下事件代码:

Input device events(输入设备事件)

显示原文

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 (长按重复时间)毫秒后,调用一次。如果被滚动,则不会被调用。

LV_EVENT_CLICKED : 如果没有被滚动,在释放时被调用(与长按无关)

LV_EVENT_RELEASED : 在任何对象释放时被调用

LV_EVENT_SCROLL_BEGIN : 滚动开始。事件参数是滚动动画的指针。可以被修改

LV_EVENT_SCROLL_THROW_BEGIN :

LV_EVENT_SCROLL_END : 滚动结束

LV_EVENT_SCROLL : 滚动中

LV_EVENT_GESTURE : 检测到手势。使用

lv_indev_get_gesture_dir(lv_indev_active()); 获取手势

LV_EVENT_KEY : 将键发送给对象。使用 lv_indev_get_key(lv_indev_active()); 获取键值

LV_EVENT_FOCUSED : 对象获得焦点 LV_EVENT_DEFOCUSED : 对象失去焦点 LV_EVENT_LEAVE : 对象失去焦点但仍然被选中 LV_EVENT_HIT_TEST : 执行高级点击测试 LV_EVENT_INDEV_RESET : 输入设备已重置 LV_EVENT_HOVER_OVER : 输入设备悬停在对象上方。

LV_EVENT_HOVER_LEAVE : 输入设备离开对象上方的悬停状态。

Drawing events(绘图事件)

显示原文

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

:cpp:type:‘lv_cover_check_info_t *类型的指针。

LV_EVENT_REFR_EXT_DRAW_SIZE : 获取对象周围所需的额外绘制区域(例如用于阴影)。事件参数是 int32_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_TASK_ADDED : 添加绘制任务

Special events(特殊事件)

显示原文

LV_EVENT_VALUE_CHANGED : 对象的值已更改(例如,滑块移动)

LV_EVENT_INSERT : 文本已插入到对象中。事件数据是被插入的 ] (https://lvgl.100ask.net/9.2/overview/event.html#id8)char [*] (https://lvgl.100ask.net/9.2/overview/event.html#id10)[ 类型的文本。

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

LV_EVENT_READY : 进程已结束

LV_EVENT_CANCEL : 进程已取消

Other events(其他事件)

显示原文

LV_EVENT_CREATE : 对象正在被创建

LV_EVENT_DELETE : 对象正在被删除

LV_EVENT_CHILD_CHANGED : 子对象已被移除、添加,或其大小、位置已被修改 LV_EVENT_CHILD_CREATED : 子对象已被创建,总是向上冒泡到所有父对象 LV_EVENT_CHILD_DELETED : 子对象已被删除,总是向上冒泡到所有父对象 LV_EVENT_SCREEN_UNLOAD_START : 屏幕卸载已开始,在调用scr_load时立即触发 LV_EVENT_SCREEN_LOAD_START : 屏幕加载已开始,在屏幕切换延迟过后触发 LV_EVENT_SCREEN_LOADED : 屏幕已加载

LV_EVENT_SCREEN_UNLOADED : 屏幕已卸载

LV_EVENT_SIZE_CHANGED : 对象坐标/大小已更改 LV_EVENT_STYLE_CHANGED : 对象的样式已更改 LV_EVENT_LAYOUT_CHANGED : 由于布局重新计算,子对象位置已更改 LV_EVENT_GET_SELF_SIZE : 获取部件的内部大小

Display events(展示时间)

LV_EVENT_INVALIDATE_AREA

LV_EVENT_RESOLUTION_CHANGED

LV_EVENT_COLOR_FORMAT_CHANGED

LV_EVENT_REFR_REQUEST

LV_EVENT_REFR_START

LV_EVENT_REFR_READY

LV_EVENT_RENDER_START

LV_EVENT_RENDER_READY

LV_EVENT_FLUSH_START

LV_EVENT_FLUSH_FINISH

Custom events(自定义事件)

显示原文

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

它们可以发送到任何对象中,使用:

lv_event_send(obj, MY_EVENT_1, &some_data)

Fields of lv_event_tlv_event_t 的字段)与事件回调函数

显示原文

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

lv_event_get_code(e):获取事件代码

lv_event_get_current_target(e):获取事件被发送到的对象。即,正在被调用其事件处理程序的对象。

lv_event_get_target(e): 获取最初触发事件的对象(如果启用了 event bubbling

,则与 lv_event_get_target() 不同)

lv_event_get_user_data(e): 获取作为 lv_obj_add_event() 的最后一个参数传递的指针。//获取使⽤ lv_obj_add_event_cb 函数传递的⽤⼾数据

lv_event_get_param(e): 获取作为 lv_event_send() 的最后一个参数传递的参数。//获取使⽤ lv_obj_send_event 函数传递的⽤⼾数据

static void my_event_cb(lv_event_t * e)

{

lv_obj_t * obj = lv_event_get_target(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, "LV_EVENT_PRESSED"); lv_obj_set_style_bg_color(obj,

lv_color_hex(0xc43e1c), 0); // 通过本地样式(私有样式)设置背景色

LV_LOG_USER("LV_EVENT_PRESSED\n");

break;

case LV_EVENT_LONG_PRESSED:

lv_label_set_text(label, "LV_EVENT_LONG_PRESSED");

lv_obj_set_style_bg_color(obj, lv_color_hex(0x4cbe37), 0); // 通过本地样式(私有样式)设置背景色

LV_LOG_USER("LV_EVENT_LONG_PRESSED\n");

break;

case LV_EVENT_RELEASED:

lv_label_set_text(label, "test"); lv_obj_remove_local_style_prop(obj,

LV_STYLE_BG_COLOR, 0);

LV_LOG_USER("LV_EVENT_RELEASED\n");

break; default:

//LV_LOG_USER("NONE\n");

break;

}

}

void lesson_2_8_1(void)

{

/* 创建一个基础对象 obj1 */

lv_obj_t * obj1 = lv_obj_create(lv_screen_active()); lv_obj_set_size(obj1, 450, 250);

lv_obj_center(obj1); // 将对象与其

父对象的中心对齐,这里的父对象是屏幕:lv_screen_active()

事件与对象之间的关系

⼀个事件回调函数可给多个对象使⽤

我们创建了⼀个事件处理函数之后是可以给不同的对象使⽤的。

⼀个对象可以使⽤多个事件回调函数

我们创建的对象可以绑定多个事件,⽐如⼀个事件是处理点击类型的事件,⼀个事件处理按下类型的事件等等。

其他

如果传⼊的⽤⼾数据不⼀样,⼀个对象可以绑定同⼀个事件回调函数多次,事件将按照添加的顺序调⽤。例如:

lv_obj_add_event_cb(obj, my_clicked_event_cb, LV_EVENT_CLICKED,

&num1); lv_obj_add_event_cb(obj, my_clicked_event_cb, LV_EVENT_CLICKED, &num2);

Event bubbling(事件冒泡)

显示原文

如果启用了 lv_obj_add_flag(obj,LV_OBJ_FLAG_EVENT_BUBBLE),那么所有事件也会发送给对象的父对象。如果父对象也启用了 LV_OBJ_FLAG_EVENT_BUBBLE ,那么该事件将继续被发送给其父对象,依此类推。

事件的 target 参数始终是当前的目标对象,而不是原始对象。要获取原始目标对象,可以在事件处理函数中调用 lv_event_get_target_obj(e)。

lv_event_get_target(e); //获取触发事件的当前对象。

lv_event_get_current_target(e); //获取事件冒泡的⽗对象

/* 以 obj1 创建一个基础对象 obj2 */ lv_obj_t * obj2 = lv_obj_create(obj1);

static void my_event_cb(lv_event_t * e)

lv_obj_set_size(obj2, 400, 200);

lv_obj_center(obj2); // 将对象与其

父对象的中心对齐,这里的父对象是屏幕:obj1

lv_obj_add_flag(obj2, LV_OBJ_FLAG_EVENT_BUBBLE); // 启用事件冒泡,将接收到的所有事件传播给父级

/* 以 obj2 创建一个基础对象 obj3 */ lv_obj_t * obj3 = lv_obj_create(obj2); lv_obj_set_size(obj3, 350, 150);

lv_obj_center(obj3); // 将对象与其父对象的中心对齐,这里的父对象是屏幕:obj2

lv_obj_add_flag(obj3, LV_OBJ_FLAG_EVENT_BUBBLE); // 启用事件冒泡,将接收到的所有事件传播给父级

/* 以 obj3 创建一个基础对象 obj4 */ lv_obj_t * obj4 = lv_obj_create(obj3);

lv_obj_set_size(obj4, 300, 100);

lv_obj_center(obj4); // 将对象与其父对象的中心对齐,这里的父对象是屏幕:obj3

lv_obj_add_flag(obj4, LV_OBJ_FLAG_EVENT_BUBBLE); // 启用事件冒泡,将接收到的所有事件传播给父级

/* 以屏幕为父类,创建一个label部件(对象) */

lv_obj_t * label = lv_label_create(lv_screen_active()); lv_label_set_text(label, "test");

// 设置label展示的文字

lv_obj_align_to(label, obj1, LV_ALIGN_OUT_TOP_MID, 0, 0);

// 将label相对于obj1对齐

// 将给obj1添加事件回调函数,所有的事件类型都能触发该回调函数

lv_obj_add_event_cb(obj1, my_event_cb, LV_EVENT_ALL, label);

}

回调函数

{

lv_obj_t * obj = lv_event_get_target(e); // 获取触发事

件的对象

lv_obj_t * parent = lv_event_get_current_target(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, "LV_EVENT_PRESSED"); lv_obj_set_style_bg_color(parent,

lv_color_hex(0xc43e1c), 0); // 通过本地样式(私有样式)设置背景色

lv_obj_set_style_bg_color(obj, lv_color_hex(0xc43e1c),

0); // 通过本地样式(私有样式)设置背景色

LV_LOG_USER("LV_EVENT_PRESSED\n");

break;

case LV_EVENT_RELEASED:

lv_label_set_text(label, "LV_EVENT_RELEASED"); lv_obj_remove_local_style_prop(parent,

LV_STYLE_BG_COLOR, 0); // 删除通过本地样式(私有样式)设置的背景色

lv_obj_remove_local_style_prop(obj, LV_STYLE_BG_COLOR, 0); // 删除通过本地样式(私有样式)设置的背景色

LV_LOG_USER("LV_EVENT_RELEASED\n");

break; default:

//LV_LOG_USER("NONE\n");

break;

}

}

解析

本次代码首先对应的两个函数的区别

void *lv_event_get_current_target(lv_event_t *e)

/*获取事件的当前目标。它是被调用的事件处理程序的对象。如果事件未被冒泡,则与“正常

目标相同。

参数:e -- 事件描述符的指针

返回:指向event_code当前的目标

*/

void *lv_event_get_target(lv_event_t *e)

/*获取事件最初被目标的对象。即使事件被冒泡,它也是一样的。参数:e -- 指向事件描述符的指针

返回:事件代码的目标对象

*/

 

posted @ 2026-07-30 17:59  哲别羽  阅读(5)  评论(0)    收藏  举报