FULL PRODUCT VERSION :
openjdk version "1.8.0_151"
OpenJDK Runtime Environment (build 1.8.0_151-8u151-b12-0ubuntu0.17.10.2-b12)
OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux My-PC 4.13.0-21-generic #24-Ubuntu SMP Mon Dec 18 17:29:16 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
I have a TextField and a TableView in a BorderPane.
I wanted to assign program-wide hotkey to the program for the key s, so I put a EventListener <KeyEvent> on the BorderPane.
This seemed to work perfectly -- events pressed on the table were passed through to the BorderPane but events in the TextField that created text were consumed before getting to my listener.
I then wanted to add a similar hotkey for Shift + s. In this case, the TextField does not consume the KeyEvent, so it types the letter S (capital) into the TextField but also passes the key event to my BorderPane rather than consuming the event.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run this program
Press s while Tableview has focus -- "Heard s" is printed -- good
Press s while TextField has focus -- nothing is printed and the s is put in the text box -- good
Press shift + s while Tableview has focus -- "Heard Shift + s" is printed -- good
Press shift + s while TextField has focus -- "Heard Shift + s" is printed and S is put in the text box -- BAD -- nothing should print.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
In step 5, expect "Heard Shift + s" to not print
ACTUAL -
In step 5, expect "Heard Shift + s" is printed
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.Locale;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class KeyEventIssue extends Application {
@Override
public void start ( Stage stage ) throws Exception {
TextField textInput = new TextField();
TableView <Locale> table = getFilledTable();
BorderPane primaryContainer = new BorderPane();
primaryContainer.setTop( textInput );
primaryContainer.setCenter( table );
primaryContainer.setOnKeyPressed( ( KeyEvent e ) -> {
if ( e.getCode() == KeyCode.S
&& !e.isControlDown() && !e.isAltDown() && !e.isShiftDown() && !e.isMetaDown() ) {
System.out.println ( "Heard s" );
e.consume();
} else if ( e.getCode() == KeyCode.S && e.isShiftDown()
&& !e.isControlDown() && !e.isAltDown() && !e.isMetaDown() ) {
System.out.println ( "Heard Shift + s" );
e.consume();
}
});
Scene scene = new Scene( primaryContainer );
stage.setScene( scene );
stage.setWidth( 700 );
stage.show();
}
private TableView <Locale> getFilledTable () {
TableView <Locale> table = new TableView <>( FXCollections.observableArrayList( Locale.getAvailableLocales() ) );
TableColumn <Locale, String> countryCode = new TableColumn <>( "CountryCode" );
countryCode.setCellValueFactory( new PropertyValueFactory <>( "country" ) );
TableColumn <Locale, String> language = new TableColumn <>( "Language" );
language.setCellValueFactory( new PropertyValueFactory <>( "language" ) );
TableColumn <Locale, Locale> local = new TableColumn <>( "Locale" );
local.setCellValueFactory( c -> new SimpleObjectProperty <>( c.getValue() ) );
language.setCellValueFactory( new PropertyValueFactory <>( "language" ) );
table.setColumnResizePolicy( TableView.CONSTRAINED_RESIZE_POLICY );
table.getColumns().addAll( countryCode, language, local );
return table;
}
public static void main ( String[] args ) {
Application.launch ( args );
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
You can manually check to see if the text area has focus before printing. This is unwieldy in a larger program, but can be done. Could lead to difficult to maintain code.