JDK-8194280 : Inconsistent KeyEvent Consumption by TextField
  • Type: Bug
  • Component: javafx
  • Sub-Component: controls
  • Affected Version: 8u152
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2018-01-02
  • Updated: 2018-01-02
  • Resolved: 2018-01-02
Related Reports
Duplicate :  
Description
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. 


Comments
This is a duplicate of JDK-8089884, that has been fixed in JDK 9. Closing this as Duplicate, as it is not a regression and affects JDK 7, 8 family and not JDK 9,10. Try JDK 9 and later releases.
02-01-2018