У меня проблема с обнаружением одного нажатия клавиши в JavaFX. Я должен обнаруживать клавиши со стрелками, но каждый раз, когда я нажимаю любую из этих клавиш, часть моего кода вызывается несколько раз. Я понимаю, что это потому, что AnimationTimer()
- это цикл, поэтому это причина, но я понятия не имею, как обнаружить однократное нажатие клавиши. В любом случае, вот код:Обнаружение нажатия одной клавиши в JavaFX
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import java.util.HashSet;
public class Main extends Application {
Stage window;
static Scene scene;
private static char[][] mapa = {
{'X','X','X','X','X'},
{'X','.','.','.','X'},
{'X','.','M','.','X'},
{'X','.','.','.','X'},
{'X','X','X','X','X'}
};
private final int sizeX = 16;
private final int sizeY = 16;
static HashSet<String> currentlyActiveKeys;
@Override
public void start(Stage primaryStage) throws Exception {
window = primaryStage;
window.setTitle("Hello World");
Group root = new Group();
scene = new Scene(root);
window.setScene(scene);
Canvas canvas = new Canvas(512 - 64, 256);
root.getChildren().add(canvas);
prepareActionHandlers();
GraphicsContext gc = canvas.getGraphicsContext2D();
new AnimationTimer() {
@Override
public void handle(long now) {
gc.clearRect(0,0,512,512);
for(int i = 0; i < mapa.length; i++) {
for(int j = 0; j < mapa[i].length; j++) {
if(mapa[i][j] == 'X') {
gc.setLineWidth(5);
gc.setFill(Color.RED);
gc.fillRect(sizeX + i*sizeX, sizeY + j*sizeY, sizeX, sizeY);
} else if(mapa[i][j] == '.') {
gc.setLineWidth(5);
gc.setFill(Color.GREEN);
gc.fillRect(sizeX + i*sizeX, sizeY + j*sizeY, sizeX, sizeY);
} else if(mapa[i][j] == 'M') {
gc.setLineWidth(5);
gc.setFill(Color.BLACK);
gc.fillRect(sizeX + i*sizeX, sizeY + j*sizeY, sizeX, sizeY);
}
}
}
if(currentlyActiveKeys.contains("LEFT")) {
System.out.println("left");
}
if(currentlyActiveKeys.contains("RIGHT")) {
System.out.println("right");
}
if(currentlyActiveKeys.contains("UP")) {
System.out.println("up");
}
if(currentlyActiveKeys.contains("DOWN")) {
System.out.println("down");
}
}
}.start();
window.show();
}
private static void prepareActionHandlers()
{
currentlyActiveKeys = new HashSet<String>();
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event)
{
currentlyActiveKeys.add(event.getCode().toString());
}
});
scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event)
{
currentlyActiveKeys.remove(event.getCode().toString());
}
});
}
public static void main(String[] args) {
launch(args);
}
}
При нажатии вниз кнопки со стрелкой (то же самое с другими клавишами, конечно), в объеме я получаю результаты, как:
down
down
down
down
down
down
Очевидно, что это происходит, как пока я нажимаю кнопку. Как только я перестаю нажимать, печать заканчивается. То, что я хотел бы добиться, это то, что как только я нажму кнопку (независимо от того, как долго я ее удерживаю), я получу down
только один раз. Мне нужно это, потому что я хотел бы обновить цвет моих прямоугольников в canvas
.
Это [связанные вопрос] (http://stackoverflow.com/questions/29962395/how-to-write-a-keylistener-for-javafx) может помочь (или может не). Я предполагаю, что вы пытаетесь сделать что-то другое. – jewelsea
@jewelsea Я редактировал код и вставил неправильную версию. Теперь есть 'setOnKeyPressed' – Lisek
@jewelsea При нажатии стрелок герой непрерывно перемещается. В моем примере я хотел бы, чтобы герой просто сделал один шаг, даже если я удерживаю ключ. Это не работает. Удерживая кнопку, я получаю несколько отпечатков. – Lisek