I am trying to implement LEFT RIGHT movement of a rectangle shape in JavaFX. Below is my code:
public void start(Stage primaryStage) throws Exception {
I would use an AnimationTimer for moving the rectangle, and just update a property representing the velocity on key pressed or key released:
final Rectangle rect = ... ;
final double rectangleSpeed = 100 ; // pixels per second
final double minX = 0 ;
final double maxX = 800 ; // whatever the max value should be.. can use a property and bind to scene width if needed...
final DoubleProperty rectangleVelocity = new SimpleDoubleProperty();
final LongProperty lastUpdateTime = new SimpleLongProperty();
final AnimationTimer rectangleAnimation = new AnimationTimer() {
@Override
public void handle(long timestamp) {
if (lastUpdateTime.get() > 0) {
final double elapsedSeconds = (timestamp - lastUpdateTime.get()) / 1_000_000_000.0 ;
final double deltaX = elapsedSeconds * rectangleVelocity.get();
final double oldX = rect.getTranslateX();
final double newX = Math.max(minX, Math.min(maxX, oldX + deltaX));
rect.setTranslateX(newX);
}
lastUpdateTime.set(timestamp);
}
};
rectangleAnimation.start();
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if (event.getCode()==KeyCode.RIGHT) { // don't use toString here!!!
rectangleVelocity.set(rectangleSpeed);
} else if (event.getCode() == KeyCode.LEFT) {
rectangleVelocity.set(-rectangleSpeed);
}
}
});
scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.LEFT) {
rectangleVelocity.set(0);
}
}
});
UPDATE:
The AnimationTimer executes its handle method once each time a frame is rendered by the JavaFX mechanism. The long passed into the handle method is a timestamp of the render frame, in nanoseconds.
The way this works is that we keep track of the last update time. The handle(...) method computes the elapsed time since the last update, multiplies it by the rectangle's velocity, and updates the translateX of the rectangle by that amount. The AnimationTimer is always running, but initially the velocity is set to zero so the rectangle doesn't move.
The keyPressed handler simply changes the velocity: to a positive value if moving right and a negative value if moving left. The keyReleased handler sets the velocity back to zero.