How to uncheck all buttons in button matrix or Tabview

Description

i want to uncheck the pressed last button if i press a second time ( apply one checked button and uncheck last one checked if i click a second time on it)
I need to have just one button checked and have the possibility to uncheck all buttons (as they are at first view of screen )

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

simulator code blocks

What LVGL version are you using?

8.1

What do you want to achieve?

uncheck the last button checked if i click a second time on it
button Martix or Tabview

What have you tried so far?

lv_btnmatrix_set_btn_ctrl_all(btnm1 , LV_BTNMATRIX_CTRL_CHECKABLE);
lv_btnmatrix_set_one_checked(btnm1, true);

Code to reproduce

Add a code snippet which can run in the simulator. It should contain only the relevant code that compiles without errors when separated from your main code base.

The code block(s) should be formatted like:

/*
    lv_obj_t *btnm1;
	btnm1 = lv_btnmatrix_create(ui->screen);
	lv_obj_set_pos(btnm1, 0, 320);
	lv_obj_set_size(btnm1, 500, 50);
	static const char *btnm1_map[] = {"overview","home"," Test ","Configuration","Help"};
	lv_btnmatrix_set_map(btnm1, btnm1_map);
  
    lv_btnmatrix_set_one_checked(btnm1, true);
    lv_btnmatrix_set_btn_ctrl_all(btnm1 , LV_BTNMATRIX_CTRL_CHECKABLE);
*/

Screenshot and/or video

First View ( all buttons are unchecked)
image

here all time i have one button activated, i think it’s due to : lv_btnmatrix_set_one_checked()
how to uncheck all buttons ?
image

how can i access to state of button those are configured as Checkable, i’ve tried to write the code bellow to Check the state of one of my buttons,

static void event_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * obj = lv_event_get_target(e);

    lv_state_t BOD = lv_obj_get_state(obj);
    uint32_t id = lv_btnmatrix_get_selected_btn(obj);
    const char * txt = lv_btnmatrix_get_btn_text(obj, id);

if(code == LV_EVENT_VALUE_CHANGED)
{

    switch(BOD) {
        case LV_STATE_CHECKED:
            LV_LOG_USER(" %s LV_STATE_CHECKED" ,txt);
            break;
        case LV_STATE_FOCUSED:
            LV_LOG_USER(" %s LV_STATE_FOCUSED",txt);
            break;
        case LV_STATE_DEFAULT:
            LV_LOG_USER(" %s LV_STATE_DEFAULT",txt);
            break;
        case LV_STATE_FOCUS_KEY:
            LV_LOG_USER( " %s LV_STATE_FOCUS_KEY",txt);
            break;
        case LV_STATE_EDITED:
            LV_LOG_USER( " %s LV_STATE_EDITED",txt);
        break;
        case LV_STATE_HOVERED:
            LV_LOG_USER( " %s LV_STATE_HOVERED",txt);
            break;
        case LV_STATE_PRESSED :
            LV_LOG_USER( " %s LV_STATE_PRESSED ",txt);
            break;
        case LV_STATE_DISABLED:
            LV_LOG_USER( " %s LV_STATE_DISABLED",txt);
            break;
        case LV_STATE_SCROLLED:
            LV_LOG_USER( " %s LV_STATE_SCROLLED",txt);
            break;
        default:
            LV_LOG_USER( "%s Uknown State Value : 0x%.4x",txt,BOD);
            break;
    }
}
}

the first click i get LV_STATE_PRESSED, and I’m supposed to have a Checked status
I get the value 0x0022 for the state after the first click, as u see on the screenshot

how can i get the state (checked or not) ?

Hi @Zebra067 ,

The states are represented by ‘bits’ so the value of ‘BOD’ can represent multiple states at any point in time, so the value 0x0022 for example means the object is both ‘focused’ and ‘pressed’ at the same time. Does that make sense?

I would change the logic of your event callback to something like this:

static void event_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * obj = lv_event_get_target(e);

    lv_state_t BOD = lv_obj_get_state(obj);
    uint32_t id = lv_btnmatrix_get_selected_btn(obj);
    const char * txt = lv_btnmatrix_get_btn_text(obj, id);

	if(code == LV_EVENT_VALUE_CHANGED)
	{

		if( BOD & LV_STATE_CHECKED ) LV_LOG_USER(" %s LV_STATE_CHECKED" ,txt);
		if( BOD & LV_STATE_FOCUSED ) LV_LOG_USER(" %s LV_STATE_FOCUSED",txt);
		if( BOD & LV_STATE_DEFAULT ) LV_LOG_USER(" %s LV_STATE_DEFAULT",txt);
		if( BOD & LV_STATE_FOCUS_KEY ) LV_LOG_USER( " %s LV_STATE_FOCUS_KEY",txt);
		if( BOD & LV_STATE_EDITED ) LV_LOG_USER( " %s LV_STATE_EDITED",txt);
		if( BOD & LV_STATE_HOVERED ) LV_LOG_USER( " %s LV_STATE_HOVERED",txt);
		if( BOD & LV_STATE_PRESSED ) LV_LOG_USER( " %s LV_STATE_PRESSED ",txt);
		if( BOD & LV_STATE_DISABLED ) LV_LOG_USER( " %s LV_STATE_DISABLED",txt);
		if( BOD & LV_STATE_SCROLLED ) LV_LOG_USER( " %s LV_STATE_SCROLLED",txt);
	}
}

I think if you combine this logic change with the answer here from @kisvegabor on your other post, you should be able to achieve you goals.

I hope that helps.

Kind Regards,

Pete

1 Like

Hi @pete-pjb,

Thank’s for your answer.

Yes, I understand that’s the states are represented by ‘bits’, but I don’t understand how to have in my case the state of the button (checked/unchecked) ,

I changed my code to the part you suggested, and I tried it without the one checked mode, only Checkable.
The problem is: I never get the checked state, only pressed and focused.

first click (button home state is pressed)

Second click (to uncheck button home), i get 2 states :

  • LV_STATE_FOCUSED
  • LV_STATE_PRESSED

So i can’t get the state of my button to use the answer from @kisvegabor,

excuse my bad english , I hope you understand my issue,

Thank you,

Zebra

Hi @Zebra067 ,

I see…

I haven’t tried this but you could try calling the function:

 bool lv_btnmatrix_has_btn_ctrl( obj, id, LV_BTNMATRIX_CTRL_CHECKED );

inside your event call back to get the state of the button?

Is that helpful?

Kind Regards,

Pete

1 Like

thank you! that’s function make me know if the button is checked.

I tried this in 2 cases (just checkable and one checked mode )

 bool checked1 = lv_btnmatrix_has_btn_ctrl( obj, id, LV_BTNMATRIX_CTRL_CHECKED );
/* to uncheck */
if(checked1)lv_btnmatrix_clear_btn_ctrl_all(obj, LV_BTNMATRIX_CTRL_CHECKED);
/* or */
lv_btnmatrix_clear_btn_ctrl(obj,id, LV_BTNMATRIX_CTRL_CHECKED);

Case only checkable :

  • i cannot uncheck buttons after making them checked. ( i assume that it’s setting state and block the state in checked instead of clearing the state checked. (i don’t know if it’s a bug or it’s really programmed like this.)

Case One checked :

  • it’s not working but i see that button tries to uncheck (while i do a long press) i assume that the function lv_btnmatrix_set_one_checked() forces the button matrix to have at least one button checked whatever happened.

Hi @Zebra067 ,

Here is a simple example I have made for you which will work in the simulator, I hope this is what you are trying to achieve if I understand your questions correctly…

static void event_handler(lv_event_t * e) {

    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * obj = lv_event_get_target(e);

    if(code == LV_EVENT_PRESSED) {
        uint32_t id = lv_btnmatrix_get_selected_btn(obj);
        if( lv_btnmatrix_has_btn_ctrl( obj, id, LV_BTNMATRIX_CTRL_CHECKED ) ) {
        	lv_btnmatrix_clear_btn_ctrl(obj, id, LV_BTNMATRIX_CTRL_CHECKED);
        } else {
        	lv_btnmatrix_clear_btn_ctrl_all(obj, LV_BTNMATRIX_CTRL_CHECKED);
        	lv_btnmatrix_set_btn_ctrl(obj, id, LV_BTNMATRIX_CTRL_CHECKED);
        }
    }
}

static const char * btnm_map[] = {"1", "2", "3", "4", "5", "" };
void button_demo(void) {

    lv_obj_t * btnm1 = lv_btnmatrix_create(lv_scr_act());
    lv_btnmatrix_set_map(btnm1, btnm_map);
    lv_obj_align(btnm1, LV_ALIGN_CENTER, 0, 0);
    lv_obj_add_event_cb(btnm1, event_handler, LV_EVENT_PRESSED, NULL);
}

Please give this a try and let me know if this is what you are trying to achieve.

Kind Regards,

Pete

1 Like

Hi @pete-pjb,

Yes it works , Thank you so much,

So no need to use lv_btnmatrix_set_one_checked(),

I’ll try this solution if i can use it in Tabview (the button matrix part) i think in Tabview the one checked mode is applied by default.

Thank you so much,

Marouane,

1 Like

Hi @pete-pjb, @kisvegabor

I want to have the possibility to uncheck all buttons in Tabview, like the solution you gave to me for button matrix. And I’m really stuck.
What I’m trying to do is when I uncheck the buttons the container related with must disappear (hidden),

I can’t do that in my program, because Tabview is programmed in way all time a tab is checked, so what I’m trying to do is to understand how the widget works in LVGL and i try to make some modifications in lv_tabview.c

I already can’t uncheck all buttons fast (there is a bug because i don’t understand well how the widget works inside. ) I do modifications in the function void lv_tabview_set_act(lv_obj_t * obj, uint32_t id, lv_anim_enable_t anim_en); and

I’ve tried to use the function lv_obj_add_flag(cont, LV_OBJ_FLAG_HIDDEN) and it makes the button matrix change place. (it’s due to lv_obj_set_flex_flow used to define the position of tabview parts. )

So i don’t know if is it possible to make modification in tabview, or i need to create a custom widget.
I think it would be a good widget to suggest (or having this option in tabview widget)

Could you help me just to understand a little bit where I must do modification? or if you have any documents that would help me more to understand how a widget works (to create a custom widget)

Best Regards,

Marouane

As it’s not a typical tabview feature, lv_tabview is not designed to support hiding tabs this way. And as you noticed it’s a little bit hard to customize the tabview to work like this.

I think the best would be to have a custom widget which works according to your specification. We do widget development service, so please contact us via lvgl@lvgl.io and describe all the features you need from such a widget. After

1 Like

Yes, I see how tabview is designed in LVGL and other libraries too, and it’s different from what I want.

If I do in the simple way: maybe i can create manually in my code buttons and containers and link each container with a button by events, But it will make my code too long and havings a lot of objects to deal with, and i don’t know if this would affect CPU and memory usage.

I think the functionality I want is not hard as tabview, I’ll give it some more time to create the widget (that would help me understand more how LVGL and UI works),

If I couldn’t make it by myself, I’ll contact your service for sure.

Thank you,

Marouane

1 Like