-
Bug
-
Resolution: Unresolved
-
P4
-
jfx11, jfx20, jfx21, jfx22, jfx23
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
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