Search code examples
codenameone

Form shown via a Command in a Dialog doesn't show correctly


I've made my own popup/overflow menu (as discussed here: Is it possible to reuse the Toolbar Overflow menu elsewhere?).

The code worked OK, but then I added a menu command that displays another Form. When that command is clicked, the other Form just flashes by and is immediately replaced by the first form.

The code below shows this. Click "show my menu" and then click "PopupCmd" in the menu. I want the Form2 to remain visible (to allow the user to do other things and then return back to Form1), but it just flashes and Form1 is immediately shown again.

I guess I'm missing something obvious, but I've spend a lot of time debugging and testing various options without finding any solution, so I'm hoping someone can spot the issue.

Form form1 = new Form("Form1", BoxLayout.y());
form1.setName("FORM1"); //for debugging
Dialog myMenu = new Dialog("test menu dialog", BoxLayout.y());
myMenu.setName("POPUPMENU"); //for debugging
myMenu.setAutoDispose(true); 
myMenu.setDisposeWhenPointerOutOfBounds(true); 

myMenu.add(new Button(Command.createMaterial("PopupCmd", FontImage.MATERIAL_SETTINGS, (ev) -> {
    Form form2 = new Form("FORM2");
    form2.setName("FORM2"); //for debugging
    form2.show();
})));

Button showMenu = new Button("show my menu");
showMenu.addActionListener((e) -> {

    myMenu.showPopupDialog(showMenu); //get user-selected cmd
});
form1.add(showMenu);
form1.show();

Solution

  • When a Dialog is disposed it goes back to its parent Form. So what happened here is that the Command showed the new Form then its dispose call went back to the previous Form.

    You have the following options:

    myMenu.setAutoDispose(false); 
    

    That would disable the automatic disposing and solve that.

    A possible better approach would be to let the Dialog dispose and then show the next Form. This can be accomplished simply by moving the code to the next EDT cycle:

    myMenu.add(new Button(Command.createMaterial("PopupCmd", FontImage.MATERIAL_SETTINGS, 
    (ev) -> callSerially(() -> {
        Form form2 = new Form("FORM2");
        form2.setName("FORM2"); //for debugging
        form2.show();
    }))));
    

    Notice the extra wrapping of callSerially, it assumes a static import of CN.* otherwise you can write it as CN.callSerially.