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

Multiple copies of accelerator change listeners are added to MenuItems, but only 1 is removed

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • jfx20
    • jfx19
    • javafx
    • None
    • b13
    • x86_64
    • windows_10

      The MenuButtonSkinBase adds a scene listener to add and remove change listeners to the acceleratorProperty, however it also calls ControlAcceleratorSupport which does the same. Each time the MenuButton's scene changes, multiple listeners are added, but only 1 copy is removed causing the number of listeners to grow continuously.

      This test demonstrates the issue:


          @Test
          public void testMemoryButtonSkinDoesntAddAdditionalListeners() {
              MenuItem menuItem = new MenuItem("Menu Item");
              MenuButton menuButton = new MenuButton("Menu Button", null, menuItem);
              StackPane root = new StackPane(menuButton);
              StageLoader sl = new StageLoader(root);
              assertEquals(1, getListenerCount(menuItem.acceleratorProperty()));
              root.getChildren().remove(menuButton);
              assertEquals(0, getListenerCount(menuItem.acceleratorProperty()));
              root.getChildren().add(menuButton);
              assertEquals(1, getListenerCount(menuItem.acceleratorProperty()));
              sl.dispose();
          }


      Alternatively run the following app, click the button to add/remove the menu a few times, then profile and check the number of listeners created by ControlAcceleratorSupport.java, then click the button some more and check the number again. It keeps growing.


      import javafx.application.Application;

      import javafx.scene.Scene;
      import javafx.scene.control.*;

      import javafx.scene.layout.VBox;
      import javafx.stage.Stage;


      public class MenuButtonChangeListenerTest extends Application {



          @Override
          public void start(Stage primaryStage) {

              VBox root = new VBox();
              Scene scene = new Scene(root, 800, 600);
              primaryStage.setTitle("Hello World!");
              primaryStage.setScene(scene);
              primaryStage.show();
              MenuItem menuItem = new MenuItem("Menu Item");
              Menu mainMenu = new Menu("Main Menu", null, menuItem);
              MenuButton menuButton = new MenuButton("Main Menu", null, mainMenu);


              Button button = new Button("Add/Remove Menu");
              button.setOnAction((e)->{
                  if (root.getChildren().contains(menuButton)) {
                      root.getChildren().remove(menuButton);
                  }
                  else {
                      root.getChildren().add(menuButton);
                  }
              });
              root.getChildren().add(button);
          }


      }

            dwookey Dean Wookey
            dwookey Dean Wookey
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: