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);
}
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 返回的指针
显示原文
LV_EVENT_REFRESH 是一个特殊事件,因为它被设计用来让用户通知对象刷新自身。一些例子包括:
通知标签根据一个或多个变量刷新其文本(比如当前时间)
当语言发生变化时刷新标签
如果满足一些条件(比如输入了正确的PIN码),则启用一个按钮当超出限制时,为对象添加/移除样式,等等
显示原文
事件代码可以分为以下类别:- 输入设备事件 - 绘图事件 - 其他事件 - 特殊事件 - 自定义事件所有对象(如按钮/标签/滑块等)无论其类型,都会接收 输入设备、 绘图 和 其他 事件。
然而, 特殊事件 是特定于特定部件类型的。请参阅 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_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(展示时间)
Custom events(自定义事件)
显示原文
任何自定义事件代码都可以通过 uint32_t MY_EVENT_1 = lv_event_register_id() 来注册。
它们可以发送到任何对象中,使用:
lv_event_send(obj, MY_EVENT_1, &some_data)
Fields of lv_event_t(lv_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);
显示原文
如果启用了 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 -- 指向事件描述符的指针
返回:事件代码的目标对象
*/

浙公网安备 33010602011771号