FULL PRODUCT VERSION :
java version "1.8.0_66"
Java(TM) SE Runtime Environment (build 1.8.0_66-b18)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b18, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
The JavaFX TableView consumes the ENTER and ESC key even when it is not editable. This has the side effect that the default und cancel buttons in a scene are not fired on ENTER or ESC.
This is a bug, since this is what a user would expect, when using this feature. There is no need for TableView to consume these KeyEvents if the focus is not inside an editable field.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) Start test case (focus should be on the TableView)
2) Press ENTER (nothing happens)
3) Press ESC (nothing happens)
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
On ENTER or ESC the button action should fire showing a message dialog and printing to System.out
ACTUAL -
1) The default button is not activated when RETURN is pressed while the focus is on the table
1) The cancel button is not activated when ESC is pressed while the focus is on the table
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TableViewTest extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
try {
Parent root = createContents();
Scene scene = new Scene(root);
primaryStage.setTitle("Customized TableView");
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
private Parent createContents() {
VBox root = new VBox(6);
root.setPadding(new Insets(6));
root.getChildren().add(createTableView());
root.getChildren().add(createButtonPane());
return root;
}
private Node createTableView() {
ObservableList<Person> list = FXCollections.observableArrayList(
new Person("Duschinger", "Josef"),
new Person("Staudt", "Gabi"),
new Person("Engl", "Georg"),
new Person("Wunderlich", "Jaqueline"),
new Person("Keimel", "Christoph"),
new Person("EM-SOFTWARE", null)
);
TableView<Person> tableView = new TableView<>(list);
TableColumn<Person, String> colLastname = new TableColumn<>("Last Name");
colLastname.setCellValueFactory(data -> data.getValue().lastname);
tableView.getColumns().add(colLastname);
TableColumn<Person, String> colVorname = new TableColumn<>("First Name");
colVorname.setCellValueFactory(data -> data.getValue().firstname);
tableView.getColumns().add(colVorname);
return tableView;
}
private Node createButtonPane() {
HBox buttonPane = new HBox(6);
buttonPane.setPadding(new Insets(6));
buttonPane.setAlignment(Pos.CENTER_RIGHT);
final Button defaultButton = new Button();
defaultButton.setText("Default (ENTER)");
defaultButton.setDefaultButton(true);
defaultButton.setOnAction(event -> {
System.out.println("Default button action fired");
new Alert(Alert.AlertType.INFORMATION, "Default button action fired", ButtonType.OK).showAndWait();
});
buttonPane.getChildren().add(defaultButton);
final Button cancelButton = new Button();
cancelButton.setText("Cancel (ESC)");
cancelButton.setCancelButton(true);
cancelButton.setOnAction(event -> {
System.out.println("Cancel button action fired");
new Alert(Alert.AlertType.INFORMATION, "Cancel button action fired", ButtonType.OK).showAndWait();
});
buttonPane.getChildren().add(cancelButton);
return buttonPane;
}
private static class Person {
public StringProperty lastname = new SimpleStringProperty();
public StringProperty firstname = new SimpleStringProperty();
public Person(String lastname, String vorname) {
this.lastname.set(lastname);
this.firstname.set(vorname);
}
@Override
public String toString() {
if (firstname.get() == null)
return lastname.get();
return lastname.get() + ", " + firstname.get();
}
}
}
---------- END SOURCE ----------
java version "1.8.0_66"
Java(TM) SE Runtime Environment (build 1.8.0_66-b18)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b18, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
The JavaFX TableView consumes the ENTER and ESC key even when it is not editable. This has the side effect that the default und cancel buttons in a scene are not fired on ENTER or ESC.
This is a bug, since this is what a user would expect, when using this feature. There is no need for TableView to consume these KeyEvents if the focus is not inside an editable field.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) Start test case (focus should be on the TableView)
2) Press ENTER (nothing happens)
3) Press ESC (nothing happens)
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
On ENTER or ESC the button action should fire showing a message dialog and printing to System.out
ACTUAL -
1) The default button is not activated when RETURN is pressed while the focus is on the table
1) The cancel button is not activated when ESC is pressed while the focus is on the table
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TableViewTest extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
try {
Parent root = createContents();
Scene scene = new Scene(root);
primaryStage.setTitle("Customized TableView");
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
private Parent createContents() {
VBox root = new VBox(6);
root.setPadding(new Insets(6));
root.getChildren().add(createTableView());
root.getChildren().add(createButtonPane());
return root;
}
private Node createTableView() {
ObservableList<Person> list = FXCollections.observableArrayList(
new Person("Duschinger", "Josef"),
new Person("Staudt", "Gabi"),
new Person("Engl", "Georg"),
new Person("Wunderlich", "Jaqueline"),
new Person("Keimel", "Christoph"),
new Person("EM-SOFTWARE", null)
);
TableView<Person> tableView = new TableView<>(list);
TableColumn<Person, String> colLastname = new TableColumn<>("Last Name");
colLastname.setCellValueFactory(data -> data.getValue().lastname);
tableView.getColumns().add(colLastname);
TableColumn<Person, String> colVorname = new TableColumn<>("First Name");
colVorname.setCellValueFactory(data -> data.getValue().firstname);
tableView.getColumns().add(colVorname);
return tableView;
}
private Node createButtonPane() {
HBox buttonPane = new HBox(6);
buttonPane.setPadding(new Insets(6));
buttonPane.setAlignment(Pos.CENTER_RIGHT);
final Button defaultButton = new Button();
defaultButton.setText("Default (ENTER)");
defaultButton.setDefaultButton(true);
defaultButton.setOnAction(event -> {
System.out.println("Default button action fired");
new Alert(Alert.AlertType.INFORMATION, "Default button action fired", ButtonType.OK).showAndWait();
});
buttonPane.getChildren().add(defaultButton);
final Button cancelButton = new Button();
cancelButton.setText("Cancel (ESC)");
cancelButton.setCancelButton(true);
cancelButton.setOnAction(event -> {
System.out.println("Cancel button action fired");
new Alert(Alert.AlertType.INFORMATION, "Cancel button action fired", ButtonType.OK).showAndWait();
});
buttonPane.getChildren().add(cancelButton);
return buttonPane;
}
private static class Person {
public StringProperty lastname = new SimpleStringProperty();
public StringProperty firstname = new SimpleStringProperty();
public Person(String lastname, String vorname) {
this.lastname.set(lastname);
this.firstname.set(vorname);
}
@Override
public String toString() {
if (firstname.get() == null)
return lastname.get();
return lastname.get() + ", " + firstname.get();
}
}
}
---------- END SOURCE ----------