Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8219620

Menu: must update items on modifying the list while showing




       Issue: modifying the items of a Menu (aka: submenu) while it is showing
       does not update the items shown. For comparison: modifying the list of
       direct items of the contextMenu is working as expected.

       To reproduce, compile the example below, run:
       A: see tab "subMenu"
       - right click in button the show contextmenu
       - move mouse over menu to open submenu and make sure it remains open during the steps below
       - press f1
       - expected: first item of open submenu visibly removed
       - actual: no visual change
       - to verify that items are removed from the items list, press f1 until message "empty" is printed

       for comparison, see tab "direct" and do the same:
       - as expected, items are visibly removed from the showing popup
      The issue turned up in a question at SO: https://stackoverflow.com/q/54834206/203657

      The culprit seems to be ContextMenuContent that is responsible for opening/hiding submenus - it does so by calling:

          private void showSubmenu(Menu menu) {
              openSubmenu = menu;
              submenu.show(selectedBackground, Side.RIGHT, 0, 0);

      note that the items of the subMenu (== ContextMenu that's showing the items of the menu) is set once to the items of the menu, without registering any listeners: so removing the items from Menu's items doesn't keep the items of the subMenu in sync.

      A dirty (! and beware: not tested for side-effects) hack around is to

      - grab the ContextMenuContent for the menu (that is the content that contains menu)
      - reflectively access its private field subMenu
      - when changing the items in menu, reset the items in subMenu to the same

      public class MenuModifyItemsWhileShowing extends Application {

          protected Node createTabContent(boolean asSubMenu) {
              final List<String> options = Arrays.asList(

              ContextMenu cmenu = new ContextMenu();
              List<MenuItem> items;;
              if (asSubMenu) {
                  //---------- submenu: bug
                  final Menu menu = new Menu("MENU");
                  items = menu.getItems();
              } else {
                  // for comparison: directly added - behaves as expected
                  items = cmenu.getItems();

              Button button = new Button("for contextMenu");
              // on pressing f1, remove first menuItem until list empty
              cmenu.addEventFilter(KeyEvent.KEY_PRESSED, e -> {
                  if (e.getCode() == KeyCode.F1) {
                      if (!items.isEmpty()) {
                      } else {
                          System.out.println("no more items");
              return button;

          private Parent createContent() {
              TabPane pane = new TabPane();
                      new Tab("subMenu", createTabContent(true)),
                      new Tab("direct", createTabContent(false)));
              return pane;

          public void start(Stage stage) throws Exception {
              stage.setScene(new Scene(createContent()));

          public static void main(String[] args) {




            rlichten Robert Lichtenberger
            fastegal Jeanette Winzenburg
            0 Vote for this issue
            4 Start watching this issue