The official MsgBox example does not work as expected

Description

I wanted to try the Menu example, and I was surprised because it doesn’t work the way I expected. I was not able to correct the given example of doing it that way
properly. The problem is this: When he focuses and clicks on “<”, a MsgBox opens that has a Close “X” button. Now he can focus on “<” and “X” with the keys.
“<” is on the screen below the MsgBox and “X” is on the MsgBox. The example needs to be changed, in such a way that only an element inside the MsgBox can be focused.

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

ESP32-C3, ESP-IDF v5.0

What LVGL version are you using?

v8.3.9

What do you want to achieve?

When MsgBox is opened, all input device events should be forwarded to MsgBox only. At the moment it is so that “<” can also be focused, it can even be opened many times msgbox again.

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:

#include "../../lv_examples.h"

static lv_group_t * g;

static void back_event_handler(lv_event_t * e)
{
    lv_obj_t * obj = lv_event_get_target(e);
    lv_obj_t * menu = lv_event_get_user_data(e);

    if(lv_menu_back_btn_is_root(menu, obj)) {
        lv_obj_t * mbox1 = lv_msgbox_create(NULL, "Hello", "Root back btn click.", NULL, true);
        lv_obj_center(mbox1);
    }
}

void lv_example_menu_2(void)
{
    g = lv_group_get_default();
    if(g == NULL) {
        g = lv_group_create();
        lv_group_set_default(g);
    }

    lv_indev_t * cur_drv = NULL;
    for(;;) {
        cur_drv = lv_indev_get_next(cur_drv);
        if(!cur_drv) {
            break;
        }

        if(cur_drv->driver->type == LV_INDEV_TYPE_KEYPAD) {
            lv_indev_set_group(cur_drv, g);
        }

        if(cur_drv->driver->type == LV_INDEV_TYPE_ENCODER) {
            lv_indev_set_group(cur_drv, g);
        }
    }

    lv_obj_t * menu = lv_menu_create(lv_scr_act());
    lv_menu_set_mode_root_back_btn(menu, LV_MENU_ROOT_BACK_BTN_ENABLED);
    lv_obj_add_event_cb(menu, back_event_handler, LV_EVENT_CLICKED, menu);
    lv_obj_set_size(menu, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL));
    lv_obj_center(menu);

    lv_obj_t * cont;
    lv_obj_t * label;

    /*Create a sub page*/
    lv_obj_t * sub_page = lv_menu_page_create(menu, NULL);

    cont = lv_menu_cont_create(sub_page);
    label = lv_label_create(cont);
    lv_label_set_text(label, "Hello, I am hiding here");

    /*Create a main page*/
    lv_obj_t * main_page = lv_menu_page_create(menu, NULL);

    cont = lv_menu_cont_create(main_page);
    label = lv_label_create(cont);
    lv_label_set_text(label, "Item 1");

    cont = lv_menu_cont_create(main_page);
    label = lv_label_create(cont);
    lv_label_set_text(label, "Item 2");

    cont = lv_menu_cont_create(main_page);
    label = lv_label_create(cont);
    lv_label_set_text(label, "Item 3 (Click me!)");
    lv_menu_set_load_page_event(menu, cont, sub_page);

    lv_menu_set_page(menu, main_page);
}

Screenshot and/or video

If possible, add screenshots and/or videos about the current state.

Also, official example “Complex menu”, not working as expected:

https://docs.lvgl.io/8.3/examples.html#complex-menu

When the MsgBox opens, CloseBtn “X” can be selected and “<” can be selected on the page below. It is also not possible to switch to the main menu selection (Mechanics, Sound, Display)) @kisvegabor

Added creation and setting of a default group to the example

static lv_group_t * gMenu;

void Create_Menu()
{
    gMenu = lv_group_get_default();
    if(gMenu == NULL) {
       gMenu = lv_group_create();
       lv_group_set_default(gMenu);
    }

    lv_indev_set_group(cur_drv, gMenu);
    lv_group_focus_freeze(gMenu, false);

   // It is necessary to add individual elements to the group
   lv_group_add_obj(gMenu, lv_menu_get_main_header_back_btn(menu));
   // ...
}

When a submenu is opened (for example “Mechanics” in the official Menu example) it is not necessary to create a group and add elements that are visible on the submenu.

How is that? How it works internally? The group contains only elements for the sub-menu (visible on the main menu).

How to call the event function when a subMenu is opened, when it is visible on the screen?
After returning to the Menu, how to keep focus on the previously focused element?

Tnx

Hi,

Thank you for reporting the issues.

I think we need some new features in LVGL’s “group” management to handle it properly. Without some updates, it would be very cumbersome to manage.

Note that this issue happens when you have widgets on multiple screens, as you can focus the widgets on the not visible screen too.

An elegant solution could be to mark some widgets as “keep the focus”. Typically these are parent widgets (like screens or the message box), and LVGL could handle internally to not allow focusing widgets with different “keep the focus” ancestors than the currently active widget’s ancestor.

Unfortunately, I can’t work on it right now, but if you are interested in adding this feature please open anew issue on GitHub to discuss it.

If we look at the example I implemented on hardware with three external buttons (as an encoder type)
Example code from the official site

Some screenshots

  1. question
    When the “Mechanics” sub-menu is selected, I need an event that is called when the menu is opened,screen visible, loaded. Something like “LV_EVENT_SCREEN_LOADED”
    When opening the submenu, in that event function, i need to make the second element (not the first, i.e. not “<” focused)

  2. If any sub-menu contains multiple objects (see “Mechanics” and “Sound” sub-menu), somehow the entire object of the parent focused object should be visible when scrolling.

  3. When I close any submenu, I need an event function, where for example I will create and display a specific MsgBox

  4. Because of the small screen i need to enlarge and change the color of the vertical scroll line, as well as increasing the object container in certain submenus (visible in the “Mechanics” and “Sound” submenus). Zoom in X direction (left and right)

Thanks in advance for help

I solved some things. I still need to do the following:

  • change the background of the header, not the whole menu
  • change the color of the vertical scroll line
  • and most importantly, how to scroll the parent, if some element in it is selected. The entire parent should be visible on the screen (see, for example, the attached image of the selected Sound submenu)

Dear friends,

I still have problems with the three items described and listed above.

Today I created a Submenu “SetTemp”. The menu has a header size of 60 * 240. The remaining part is 180*240.

I wanted to add a bookmark or any other object to the middle of the screen. I cannot control the position of the object in any way. How to do it.

Screenshot and code attached.

//!< Create_SubMenu
lv_obj_t * Create_SubMenu(lv_obj_t * parent)
{
    lv_obj_t * subMenu = lv_menu_page_create(parent, "SetTemp");
    lv_obj_set_style_pad_hor(subMenu, lv_obj_get_style_pad_left(lv_menu_get_main_header(parent), 0), 0);

    //!< Creating and formatting the section size
    section = lv_menu_section_create(subMenu);
    lv_obj_set_width(section, lv_disp_get_hor_res(NULL));
	lv_obj_set_height(section, (lv_disp_get_ver_res(NULL) - 60));	// 60px is the height of the Manu header "Set Temp"
	lv_obj_set_style_bg_color(section, lv_palette_main(LV_PALETTE_LIME), LV_PART_MAIN);
	lv_obj_set_style_radius(section, 0, LV_PART_MAIN);
	lv_obj_set_style_bg_opa(section, LV_OPA_100, LV_PART_MAIN);
	lv_obj_set_style_border_width(section, 0, LV_PART_MAIN);

    //!< Creating a label in the middle of the section
	lv_obj_t *label = lv_label_create(section);
	lv_obj_set_width(label, 50);
	lv_obj_set_height(label, 50);
	lv_label_set_text(label,"55");
	lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN);
	lv_obj_set_style_bg_color(label, lv_palette_main(LV_PALETTE_ORANGE), LV_PART_MAIN);
	lv_obj_set_style_radius(label, 0, LV_PART_MAIN);
	lv_obj_set_style_bg_opa(label, LV_OPA_100, LV_PART_MAIN);
	lv_obj_set_style_border_width(label, 0, LV_PART_MAIN);
	lv_obj_set_align(label, LV_ALIGN_CENTER);

	return subMenu;
}

Try to add
lv_obj_add_flag(label, LV_OBJ_FLAG_IGNORE_LAYOUT);

When “<” is clicked inside a submenu, before returning to the previous menu (or returning from the menu), for example, I want to open the MsgBox. Depending on the user’s choice (“yes” to exit or “no” to stay on the current submenu). How can I call an event and implement the requested routine in it?

If in the original example, and open the submenu Settings → About → Software information, i.e. if I am in any submenu of submenus, and if I want to implement a “Home” button, which would call a function to jump to the StartScreen, how to properly delete Menu objects and its event functions, because an error occurs (the event of a non-existent object is called).

Please help, because i have been looking for a solution to the problem for a long time. @kisvegabor

Thank you very much

I’m sorry, but I can’t immerse in it now. :frowning: I made a quick test, but I don’t know the menu widget well enough to give a solution immediately. Hopefully someone from the community can take a deeper look.