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)

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

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