javafxfxmlonkeypresskey-events

How do I create KeyEvents in Java FXML?


I created this small project to test key events. But when I press keys, it isn't behaving as I want. Actually I need key events for my Calculator project. I created a Calculator project and aside from mouse clicks, I want to add a feature where numbers or operators can be typed from a keyboard. Can anyone check this and help make it more functional?

public class FXMLDocumentController implements Initializable{

@FXML
private Label label;

@FXML
private Button backSpace;

@FXML
private Button spaceBar;

@FXML
private Button enter;

@FXML
void typedBS(KeyEvent event) {
    if (event.getCode() == KeyCode.BACK_SPACE) {
        label.setText(event.getText() + " typed.");
    }
}

@FXML
void typedE(KeyEvent event) {
    if (event.getCode()==KeyCode.ENTER) {
        label.setText(event.getText() + " typed");
    }
}

@FXML
void typedSB(KeyEvent event) {
    if (event.getCode()==KeyCode.SPACE) {
        label.setText(event.getText()+" typed");
    }
}

@FXML
void PressBackSpace(KeyEvent event) {
    if (event.getCode() == KeyCode.BACK_SPACE) {
        label.setText("You pressed Back Space key!");
    }
}

@FXML
void clickBackSpace(ActionEvent event) {
    label.setText("You clicked Back Space key!");
}

@FXML
void clickEnter(ActionEvent event) {
    label.setText("You clicked Enter key!");
}

@FXML
void clickSpaceBar(ActionEvent event) {
    label.setText("You clicked SpaceBar key!");
}

@FXML
void pressEnter(KeyEvent event) {
    if (event.getCode() == KeyCode.ENTER) {
        label.setText("You pressed Enter key!");
    }
}

@FXML
void pressSpaceBar(KeyEvent event) {
    if (event.getCode() == KeyCode.SPACE) {
        label.setText("You pressed SpaceBar key!");
    }
}

@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
}

}


Solution

  • If you look at this FXML file you can see my root node(The AnchorPane) has an onKeyPressed and onKeyReleased.

    <AnchorPane id="AnchorPane" onKeyPressed="#handleOnKeyPressed" onKeyReleased="#handleOnKeyReleased" prefHeight="650.0" prefWidth="855.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="atmfx.FXMLDocumentController">
       <children>
          <BorderPane layoutX="263.0" layoutY="94.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
             <left>
                <AnchorPane fx:id="apLeftDisplay" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
                   <children>
    

    In The Controller my method that handles these two KeyEvents are

    @FXML
    private void handleOnKeyReleased(KeyEvent event)
    {
        System.out.println();
        Button tempButton = buttons.get(event.getText());
        System.out.println("Released key text: " + event.getText());
        System.out.println("Released key code: " + event.getCode());
    
        if (tempButton != null) {
            tempButton.disarm();
            tempButton.setStyle("");
        }
        else if (event.getCode().equals(KeyCode.ENTER)) {
            tempButton = buttons.get("enter");
            tempButton.disarm();
            tempButton.setStyle("");
        }
        else if (event.getCode().equals(KeyCode.BACK_SPACE)) {
            tempButton = buttons.get("backspace");
            tempButton.disarm();
            tempButton.setStyle("");
        }
        else if (event.getCode().equals(KeyCode.SPACE)) {
            tempButton = buttons.get("space");
            tempButton.disarm();
            tempButton.setStyle("");
        }
    }
    
    @FXML
    private void handleOnKeyPressed(KeyEvent event)
    {
        Button tempButton = buttons.get(event.getText());
        System.out.println("Pressed key text: " + event.getText());
        System.out.println("Pressed key code: " + event.getCode());
        if (tempButton != null) {
            tempButton.arm();
            tempButton.setStyle("-fx-background-color: blue");
        }
        else if (event.getCode().equals(KeyCode.ENTER)) {
            tempButton = buttons.get("enter");
            tempButton.arm();
            tempButton.setStyle("-fx-background-color: blue");
        }
        else if (event.getCode().equals(KeyCode.BACK_SPACE)) {
            tempButton = buttons.get("backspace");
            tempButton.arm();
            tempButton.setStyle("-fx-background-color: blue");
        }
        else if (event.getCode().equals(KeyCode.SPACE)) {
            tempButton = buttons.get("space");
            tempButton.arm();
            tempButton.setStyle("-fx-background-color: blue");
        }
    }
    

    In this code I added all of my buttons to a HasMap. That way in my keyevent handlers I was able to retrieve the button depending on the keyboard key I pressed.

    Map<String, Button> buttons = new HashMap<>();
    TheButtonsParentNode.getChildren().stream().filter((tempNode)
                -> (tempNode instanceof Button)).map((
                tempNode) -> (Button) tempNode).forEachOrdered((tempButton) -> {
            buttons.put(tempButton.getText().toLowerCase(), tempButton);//adding button text and the button to hashmap
        });