【LVGL(4)】对象的事件及事件冒泡

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,这样就能实现简单的函数调用功能了,至少目前一直到开发板上可以当个点灯开关使用了。

猜你喜欢

转载自blog.csdn.net/qq_41650023/article/details/125260000
今日推荐