LVGL官方文档:Welcome to the documentation of LVGL! — LVGL documentationhttps://docs.lvgl.io/master/index.html
事件(events)
点击、滚动、数组改变、重绘……
事件类型
- 输入设备事件(Input device events)
- 绘图事件(Drawing events)
- 其他事件(Special events)
- 特殊事件(Other events)
- 自定义事件(Custom events)
看文档啦 ~ Events — LVGL documentation
添加事件
lv_obj_add_event_cb(obj, event_cb, event_code, user_data);
参数:对象,处理(cb:callbackfunction,回调函数),事件类型,用户数据
发送事件
lv_event_send(obj, event_cb, event_code, user_data);
删除事件
lv_obj_remove_event_cb(obj, event_cb);
lv_obj_remove_event_dsc(obj, event_dsc); //event_dsc 是 lv_obj_add_event_cb 返回的指针
最简单的事件:
static void function()
{
printf("test\n");
}
void mode(void)
{
lv_obj_t * obj = lv_obj_create(lv_scr_act());
lv_obj_add_event_cb(obj,function,LV_EVENT_CLICKED,NULL); //按键点击,释放后调用
}
被调用的函数是可以传入参数的
function(lv_event_t * e)
typedef struct _lv_event_t {
struct _lv_obj_t * target; //触发事件的对象
struct _lv_obj_t * current_target; //父级触发事件的对象
lv_event_code_t code; //事件代码
void * user_data; //用户数据
void * param;
struct _lv_event_t * prev;
uint8_t deleted : 1;
uint8_t stop_processing : 1;
uint8_t stop_bubbling : 1;
} lv_event_t;
如下,写了个点灯的接口
int count = 0;
static void function1(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); // 获取添加事件时传递的用户数据
if(count == 0 && code == LV_EVENT_PRESSED)
{
lv_label_set_text(label, "OPEN");
lv_obj_set_style_bg_color(obj, lv_color_hex(0xc43e1c), 0); // 通过本地样式(私有样式)设置背景色
printf("OPEN\n");
count ++;
}
else if(count == 1 && code == LV_EVENT_PRESSED)
{
lv_label_set_text(label, "CLOSE");
lv_obj_set_style_bg_color(obj, lv_color_hex(0xffffff), 0); // 通过本地样式(私有样式)设置背景色
printf("CLOSE\n");
count ++;
}
if(count==2)
count = 0;
}
void lv_100ask_demo_course_2_2_6(void)
{
/* 创建基础部件(对象) */
lv_obj_t * obj = lv_obj_create(lv_scr_act());
lv_obj_center(obj); //放在中心
/* 创建label部件(对象) */
lv_obj_t * label = lv_label_create(lv_scr_act());
lv_label_set_text(label, "CLOSE"); // 设置label展示的文字
lv_obj_center(label); // 将对象与其父对象的中心对齐,这里的父对象是屏幕:lv_scr_act()
// 为obj1添加事件回调函数,所有的事件类型都能触发该回调函数
lv_obj_add_event_cb(obj, function1, LV_EVENT_ALL, label);//传入的是label,可设置label
}
现象:
点击开灯:
点击关灯:
事件冒泡
如果对象启用了 lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE),该对象的所有事件将会发送到该对象的父级。如果父级也启用了 LV_OBJ_FLAG_EVENT_BUBBLE,那么事件继续发送到他的父级,依此类推。
- lv_event_get_target(e); 获取触发事件的当前对象。
- lv_event_get_current_target(e); 获取事件冒泡的父对象。
static void my_event_cb(lv_event_t * e)
{
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); // 通过本地样式(私有样式)设置背景色
printf("LV_EVENT_PRESSED\n");
break;
case LV_EVENT_CLICKED: //松开的时候产生了点击
lv_label_set_text(label, "LV_EVENT_CLICKED");
lv_obj_remove_local_style_prop(parent, LV_STYLE_BG_COLOR, 0); // 删除通过本地样式(私有样式)设置的背景色
lv_obj_remove_local_style_prop(obj, LV_STYLE_BG_COLOR, 0); // 删除通过本地样式(私有样式)设置的背景色
printf("LV_EVENT_CLICKED\n");
break;
default:
//printf("NONE\n");
break;
}
}
void lv_100ask_demo_course_2_2_6(void)
{
/* 创建一个基础对象 obj1 */
lv_obj_t * obj1 = lv_obj_create(lv_scr_act());
lv_obj_set_size(obj1, 450, 250);
lv_obj_center(obj1); // 将对象与其父对象的中心对齐,这里的父对象是屏幕:lv_scr_act()
/* 以 obj1 创建一个基础对象 obj2 */
lv_obj_t * obj2 = lv_obj_create(obj1);
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_scr_act());
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_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);
OK,这样就能实现简单的函数调用功能了,至少目前一直到开发板上可以当个点灯开关使用了。