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

Controls' behavior must not depend on sequence of handler registration




      The problem is that (f.i.) a button's action is fired / or not depending on whether a consuming keyEvent handler is registered after/before showing it. The example below has two buttons, both have added keyPressed handlers for ENTER which consume the key (sibling keyHandlers are registered only to see that they are notified as expected) and an action handler. The difference is that for before/after the handlers are registered before/after showing the stage.

      To reproduce, compile and run the example below
      - focus the before button
      - press enter: the action is not fired
      - focus the after button
      - press enter: the action is fired

      Whatever the expected behavior is (I lean to the behavior of first - that's the same as in pre-fx9 and Swing), it must be the same, sequence of listener registration must not make a difference.

      Technically, the reason is the InputMap that is registered as eventHandler by any XXBehavior: its handle does nothing if the event is null or consumed

          @Override public void handle(Event e) {
              if (e == null || e.isConsumed()) return;

      This handler is a sibling of the custom handlers, so served in sequence of registration. The inputMap is instantiated/registered at the time of skin instantiation. Consequently, its body is processed depending on whether a consuming handler (of the same type) is added before or after the skin creation.

      The example:

          public class AddEventHandler extends Application {
              private Button before;
              private Button after;
              // non-mac only (mac has this binding deactivated by interceptor)
              // private KeyCode consumeWith = KeyCode.ENTER;
              // this should be active for all OS
              private KeyCode consumeWith = KeyCode.SPACE;
              protected void registerHandlers(Button button) {
                  button.addEventHandler(KEY_PRESSED, e -> {
                      if (e.getCode() == consumeWith) {
                      System.out.println(e.getCode() + " received in first");
                  button.addEventHandler(KEY_PRESSED, e -> {
                      System.out.println(e.getCode() + " received in second");
                  button.setOnKeyPressed(e -> {
                  button.setOnAction(a -> {
              private Parent createContent() {
                  // some simple control that's focusable
                  before = new Button("handlers registered BEFORE showing");
                  after = new Button("handlers registered AFTER showing");
                  VBox content = new VBox(10, before, after);
                  return content;
              public void start(Stage stage) throws Exception {
                  stage.setScene(new Scene(createContent()));
              public static void main(String[] args) {
              private static final Logger LOG = Logger




            aghaisas Ajit Ghaisas
            fastegal Jeanette Winzenburg
            0 Vote for this issue
            2 Start watching this issue