Using the value/name of the object that triggered an event

Description

I’m trying to get the name of the button that was pressed in the callback function.

Perhaps I’m just looking at this wrong but I have a handful of buttons on a 3.5" touchscreen. The UI is all working and I’m having no problems updating Labels via code.

I want the buttons to fire off independent code, away from LVGL functions. An example would be a Serial.println() call, when a button is pressed.

I figured, the likes of:

lv_obj_add_event_cb(objects.btn_up, btn_click_event_handler, LV_EVENT_CLICKED, NULL);
lv_obj_add_event_cb(objects.btn_down, btn_click_event_handler, LV_EVENT_CLICKED, NULL);
lv_obj_add_event_cb(objects.btn_left, btn_click_event_handler, LV_EVENT_CLICKED, NULL);
lv_obj_add_event_cb(objects.btn_right, btn_click_event_handler, LV_EVENT_CLICKED, NULL);

Should work - i.e using a single callback for all buttons, because it would appear that I can then determine the button that fired by:
lv_obj_t *btn = (lv_obj_t *)lv_event_get_target(e);

within the callback function. However, I can’t seem to wrap my head around actually using the btn variable to determine the pressed button.

I was trying to test with something like:
lv_label_set_text(objects.lbl_status, btn);

but it doesn’t work because btn is an object, not a string. All references/examples I can find only have one button, and one callback.

The ‘easy’ alternative is to have a callback function for every button but this seems illogical to me if the calling button can be referenced - I just don’t know how to use it!

What MCU/Processor/Board and compiler are you using?

STM32F407VGT6 ‘barebones’ with Arduino

What LVGL version are you using?

9.2.2

What do you want to achieve?

A single function that I can use for all button callbacks where the pressed button can be determined within the function.

The object in the picture consists of two objects (button and label). You cannot put text on the button object, but on the label object)
BTN

The label is inside the button, i.e. label is a child of button.
If the label is the only child of the button, then you need to retrieve the first child in the interrupt function, and place the desired text on that object

void CreateBtn()
{
    lv_obj_t * btn = lv_btn_create(lv_scr_act());    
    lv_obj_set_pos(btn, 10, 10);                            
    lv_obj_set_size(btn, 120, 50);                         
    lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL);           

    lv_obj_t * label = lv_label_create(btn);         
    lv_label_set_text(label, "TEXT 1");                     
    lv_obj_center(label);
}

static void btn_event_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * btn = lv_event_get_target(e);
    if(code == LV_EVENT_CLICKED) 
    {   
        lv_obj_t * label = lv_obj_get_child(btn, 0);
        if(label != NULL) {
            lv_label_set_text(label, "TEXT 2"); }
    }
}

Thanks for the reply but perhaps I was not clear. I understand all of that, but that’s not what I’m trying to achieve or asking about.

All I want to be able to do is have a single callback function for all of the buttons.

pseudo code:

function button_callback(button_pressed){
  if (button_pressed == btn_up){
    <do stuff>
}else if (button_pressed == btn_down){
    <do stuff>
}

I don’t need to write back to any button labels or interact with the LVGL objects at all.

The problem I have is (referring to the original callback snip I posted) that I am not sure how to reference/compare the object returned by lv_obj_t *btn = lv_event_get_target(e);

Is that clearer?

You can achieve that by setting user data
https://docs.lvgl.io/master/details/base-widget/event.html#adding-events-to-a-widget

lv_obj_add_event_cb(objects.btn_up, btn_click_event_handler, LV_EVENT_CLICKED, (void *) 1);
lv_obj_add_event_cb(objects.btn_down, btn_click_event_handler, LV_EVENT_CLICKED, (void *) 2);
lv_obj_add_event_cb(objects.btn_left, btn_click_event_handler, LV_EVENT_CLICKED, (void *) 3);
lv_obj_add_event_cb(objects.btn_right, btn_click_event_handler, LV_EVENT_CLICKED, (void *) 4);

void btn_click_event_handler(lv_event_t * e)
{
    uint64_t data = (uint64_t)lv_event_get_user_data(e);
   
    switch (data) {
        case 0:
             // do stuff
             break;
    }
}
1 Like

Thanks, but that still seems like the wrong way to do it - The function provides a resource to identify the button. I managed to work it out. I just needed to reference the base name, ‘objects’ in my case:

lv_obj_add_event_cb(objects.btn_up, btn_click_event_handler, LV_EVENT_CLICKED, NULL);

static void btn_click_event_handler(lv_event_t *e) {
  lv_event_code_t code = lv_event_get_code(e);              //Get the event code
  lv_obj_t *btn = lv_event_get_target(e);       //object that generated the event

  if (code == LV_EVENT_CLICKED) {
    if(btn == objects.btn_up){
      lv_label_set_text(objects.lbl_status, "Up");
    }
  }
}

So in the end, it was super simple

1 Like

Aussie I love you lol ! I struggled for nearly 2 days with button callbacks. I am using Linux, LVGL 8.4 , Arduino GIGA R1 & Gigal display shield. I understand that I could implement the callbacks in the generated EEZ studio code, but I do not know how to correctly create the actions.c file, nor use with my Arduino code. In any case I only have 4 buttons, so its just as easy to have it all in the Ard .ino file. THANK YOU SO MUCH! Kevin W