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

TextField: must not forward ENTER if actionHandler consumed the actionEvent

XMLWordPrintable

      happens if the actionHandler is registered via addEventHandler(ActionEvent), does not happen if registered via setOnAction

      To reproduce, compile and run the example
      - focus the textField
      - press Enter
      - expected: neither accelerator nor keyHandler on parent must execute
      - actual: both execute

      Example code:

      public class TextFieldActionHandler extends Application {

          private TextField textField;

          private Parent createContent() {
              textField = new TextField("added handler: ");
              textField.addEventHandler(ActionEvent.ACTION, e -> {
                  System.out.println("in added: " + e);
                  e.consume();
              });
              
              VBox pane = new VBox(10, textField);
              
              pane.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
                  System.out.println("in parent: " + e);
              });
              
              return pane;
          }

          @Override
          public void start(Stage stage) throws Exception {
              Scene scene = new Scene(createContent());
              scene.getAccelerators().put(KeyCombination.keyCombination("ENTER"),
                      () -> System.out.println("in accelerator"));
              stage.setScene(scene);
             // stage.setTitle(FXUtils.version());
              stage.show();
          }

          public static void main(String[] args) {
              launch(args);
          }

      }

      I think the reason for the misbehaviour is in TextFieldBehaviour.fire:

          @Override protected void fire(KeyEvent event) {
              TextField textField = getNode();
              EventHandler<ActionEvent> onAction = textField.getOnAction();
              ActionEvent actionEvent = new ActionEvent(textField, null);

              textField.commitValue();
              textField.fireEvent(actionEvent);
              // ---> intention not met
              if (onAction == null && !actionEvent.isConsumed()) {
                  forwardToParent(event);
              }
          }

      the intention seems to be to not forward if either the field has an onAction handler or any other handler consumed the event. The latter never happens, because node.fireEvent (ultimately) sends around copies of an event if target != node, that is handlers consuming the event do so on a copy, not on the original.

      A tentative solution might be to construct the actionEvent with both source and target set the field (working but not formally tested), that's what menuItem does in its fire method.

      set priority to p3 because this seems to play a role in other recently reported issues, like JDK-8207385 (acts as exposer of the bug in MenuItemContaine) and maybe JDK-8207759 (though that's slightly different, registering a keyhandler directly)



            fastegal Jeanette Winzenburg
            fastegal Jeanette Winzenburg
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: