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

Editable ComboBox value committed too late when there's a default Button

XMLWordPrintable

    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      Windows 11
      Java 22.0.1
      JavaFX 22.0.1

      A DESCRIPTION OF THE PROBLEM :
      With an editable ComboBox, the user can press "Enter" to commit the new value. However, if there is a default Button in the scene, then that button's on-action handler is invoked before the new value of the ComboBox is committed. This is counterintuitive. When the user fires the default button in, e.g., a form, all input should be up to date.

      The source of this issue seems to be that a default button's on-action will be fired when a KEY_PRESSED event (for "Enter") bubbles up to the Scene, but the ComboBox commits its value on a KEY_RELEASED event (for "Enter"). The KEY_PRESSED obviously happens before the KEY_RELEASED, and so the new value is committed too late.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1) Launch provided test application.
      2) Type "Hello" (or anything) into the ComboBox and press the Enter key.
      3) Observe the output in the console.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Expected to see the ComboBox's value changed first, and for the new value to be available in the button's on-action handler. The expected console output is below.

      ComboBox.onValueChanged: Hello
      Button.onAction: Hello
      ACTUAL -
      The ComboBox's value is still null when queried from the button's on-action, and then the value is updated after. Actual console output is below.

      Button.onAction: null
      ComboBox.onValueChanged: Hello

      ---------- BEGIN SOURCE ----------
      import javafx.application.Application;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.control.ComboBox;
      import javafx.scene.layout.VBox;
      import javafx.stage.Stage;

      public class Main extends Application {

        @Override
        public void start(Stage primaryStage) {
          var comboBox = new ComboBox<String>();
          comboBox.setEditable(true);
          comboBox.valueProperty().addListener((obs, ov, nv) -> {
            System.out.printf("ComboBox.onValueChanged: %s%n", nv);
          });

          var defaultButton = new Button("Default button");
          defaultButton.setDefaultButton(true);
          defaultButton.setOnAction(e -> {
            var value = comboBox.getValue();
            System.out.printf("Button.onAction: %s%n", value);
          });

          primaryStage.setScene(new Scene(new VBox(comboBox, defaultButton)));
          primaryStage.show();
        }

        public static void main(String[] args) {
          Application.launch(Main.class, args);
        }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      It's possible to for the new value to be committed earlier by adding a KEY_PRESSED event handler:

      comboBox.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
        if (e.getCode() == KeyCode.ENTER) {
          comboBox.commitValue();
        }
      });

      FREQUENCY : always


            angorya Andy Goryachev
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated: