Btnmarix widget - change btn text/symbol when a button is pressed

I have a btnmatrix and I want a button in the matrix to act like toggle on/toggle off and the the symbol to change when toggled.

So two “how two” questions

  1. How to change the symbol of a button in a btnmatrix, there is a lv_btnmatrix_get_btn_text(btnm, btn_id) but no lv_btnmatrix_set_btn_text(btnm, btn_id)

  2. how do I get a button in a btnmatrix to act as a toggle button i.e. like a power on / power off button

Or do I have to build a button matrix from individual buttons i.e. not to use the btnmatrix widget.

Thank you

BTNM

I’m not sure that’s the effect you want. Since btnm does not have a set text interface, a redrawing technique is used here. If you feel that FONTIMG is not working well, you can draw LV_SWITCH instead, the following code should provide some inspiration:

static void event_handler(lv_event_t* e)
{
    static uint8_t switch_state = 0;
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t* obj = lv_event_get_target(e);
    if (code == LV_EVENT_VALUE_CHANGED)
    {
        uint32_t id = lv_btnmatrix_get_selected_btn(obj);
        const char* txt = lv_btnmatrix_get_btn_text(obj, id);
        if(id==11)
            switch_state = 1 - switch_state;
        LV_LOG_USER("%d %s was pressed\n",id, txt);
    }
    if (code == LV_EVENT_DRAW_PART_END)
    {
        lv_obj_draw_part_dsc_t* dsc = lv_event_get_draw_part_dsc(e);

        /*When the button matrix draws the buttons...*/
        if (dsc->class_p == &lv_btnmatrix_class && dsc->type == LV_BTNMATRIX_DRAW_PART_BTN)
        {
            
            if (dsc->id == 11)
            {
                
               const char* buf[16] = { MY_SYMBOL_SWITCH_OFF"OFF", MY_SYMBOL_SWITCH_ON"On" };
               
               lv_point_t size;
               lv_txt_get_size(&size, buf[switch_state], &font_syht_16, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE);
               lv_area_t a;
               a.x1 = dsc->draw_area->x1 + (lv_area_get_width(dsc->draw_area)- size.x) / 2;
               a.x2 = a.x1 +size.x - 1;
               a.y1 = dsc->draw_area->y1 + (lv_area_get_height(dsc->draw_area) - size.y) / 2;
               a.y2 = a.y1 + size.y - 1;
               lv_draw_label_dsc_t draw_label_dsc;
               lv_draw_label_dsc_init(&draw_label_dsc);
               draw_label_dsc.font = &font_syht_16;

               lv_draw_label(dsc->draw_ctx, &draw_label_dsc, &a, buf[switch_state], NULL);
            }
        }
    }
}

static const char* btnm_map[] = { "1", "2", "3", "4", "5", "\n",
                                  "6", "7", "8", "9", "0", "\n",
    "Action1"," ", ""
};

void lv_test_btnmatrix_1(void)
{
    lv_obj_t* btnm1 = lv_btnmatrix_create(lv_scr_act());
    lv_obj_set_style_text_font(btnm1, &font_syht_16, LV_STATE_DEFAULT | LV_PART_MAIN);
    lv_btnmatrix_set_map(btnm1, btnm_map);
    lv_btnmatrix_set_btn_width(btnm1, 10, 1);        /*Make "Action1" twice as wide as "Action2"*/
    lv_btnmatrix_set_btn_ctrl(btnm1, 10, LV_BTNMATRIX_CTRL_CHECKABLE);
    //lv_btnmatrix_set_btn_ctrl(btnm1, 11, LV_BTNMATRIX_CTRL_CHECKED);
    lv_obj_align(btnm1, LV_ALIGN_CENTER, 0, 0);
    lv_obj_add_event_cb(btnm1, event_handler, LV_EVENT_ALL, NULL);
}

Many thanks. It is a lot of code just because there is no lv_set_text. I wonder what the reason was for not having it.

see here

because the buttons are not actually created but just virtually drawn on the fly.