Reputation: 273
I had some problems in a project with KeyEvent. A combo box that switch values from one to another when key Enter is pressed.
After some attempts the problem showed was that the Enter key generates 2 times the event, so the combo box apparently didn't change.
Then, I tried to make a simple test project with this snippet:
window.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if(event.getCode().equals(KeyCode.ENTER))
System.out.println("print");
}
});
The program prints twice every enter. Is it possible that KeyCode.ENTER refers to more than one key or something like this? If i change KeyCode.ENTER in something else (tried with SPACE or some letters) it works properly. Is possible to do something to solve this issue?
I made a simple project with 3 files :
Main
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class Main extends Application {
private static Stage window;
@Override
public void start(Stage primaryStage) throws Exception{
window = primaryStage;
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static Stage getWindow(){return window;}
public static void main(String[] args) {
launch(args);
}
}
Controller:
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable {
@FXML
TextField textField;
Stage window;
@Override
public void initialize(URL location, ResourceBundle resources) {
window = Main.getWindow();
window.addEventFilter(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if (event.getCode().equals(KeyCode.ENTER))
System.out.println("print");
}
});
}
}
Sample :
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity"
minHeight="-Infinity" minWidth="-Infinity"
prefHeight="400.0" prefWidth="600.0"
fx:controller="Controller"
xmlns="http://javafx.com/javafx/8.0.121"
xmlns:fx="http://javafx.com/fxml/1">
<children>
<TextField fx:id="textField" layoutX="14.0" layoutY="14.0" />
</children>
</AnchorPane>
It prints twice when Enter is pressed. Before the insertion of the TextField instead worked as expected.
Upvotes: 3
Views: 2552
Reputation: 3187
Change this line
window.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
to
window.addEventFilter(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>() {
Edit code for @James_D
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller implements Initializable {
@FXML
TextField textField;
Stage window;
@Override
public void initialize(URL location, ResourceBundle resources) {
window = Main.getWindow();
window.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
System.out.println("Key Code:"+event.getCode()+" Target:"+event.getTarget());
});
// textField.setOnAction(event -> {});
}
}
When this runs you get the output of
Key Code:ENTER Target:TextField[id=textField, styleClass=text-input text-field]
Key Code:ENTER Target:AnchorPane@7a78d90b[styleClass=root]
If you uncomment the textField Line the output is
Key Code:ENTER Target:TextField[id=textField, styleClass=text-input text-field]
@James_D Initially I did not but after some looking around and I think it has to do with the preset setOnAction command the description is "The action handler associated with this text field, or null if no action handler is assigned. The action handler is normally called when the user types the ENTER key." So when you change the .setOnAction
to consume or nothing it prevents this error which I think is because it is no longer kicking out the enter command to the anchorPane surrounding. Now as to why the KeyEvent.KEY_RELEASED
works I think this is because the enter Key can only be released once per press down as opposed to the press which can send the command multiple times. This is all complete speculation because I have no proof of what I'm talking about if you can figure out a more reasonable explanation why I would love to know. This was supposed to be a comment but got to long.
Upvotes: 2
Reputation: 339
I had the same issue. Every key would trigger the EventFilter once, except ENTER, which would trigger it twice.
A more simple and elegant solution was to simply add e.consume()
into your block that respons to enter into the EventFilter.
if(e.getCode().toString().equals("ENTER")){
e.consume();
}
Upvotes: 1