如何在javaFX中使用KeyPress事件获得流畅的动画? [英] How to get smooth animation with KeyPress event in javaFX?

查看:27
本文介绍了如何在javaFX中使用KeyPress事件获得流畅的动画?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 JavaFX 中实现矩形的左向右移动.下面是我的代码:

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 {
    AnchorPane ancPane = new AnchorPane();      
    final Rectangle rect = new Rectangle();
    rect.setHeight(50);
    rect.setWidth(50);
    ancPane.getChildren().add(rect);
    Scene scene = new Scene(ancPane, 400, 200, Color.GREEN); 
    primaryStage.setScene(scene);
    primaryStage.show();


    scene.setOnKeyPressed(new EventHandler<KeyEvent>() {

        @Override
        public void handle(KeyEvent keyEvent) {
            System.out.println("hello");

            if(keyEvent.getCode().toString() == "RIGHT"){
                System.out.println("Move Right");
                TranslateTransition translateTransitionRight = new TranslateTransition();
                translateTransitionRight.setDuration(Duration.millis(200));
                translateTransitionRight.setNode(rect);
                translateTransitionRight.setFromX(rect.getTranslateX());
                translateTransitionRight.setToX(rect.getTranslateX()+30);
                translateTransitionRight.play();
            }

            if(keyEvent.getCode().toString() == "LEFT"){
                System.out.println("Move Left");
                TranslateTransition translateTransitionRight = new TranslateTransition();
                translateTransitionRight.setDuration(Duration.millis(200));
                translateTransitionRight.setNode(rect);
                translateTransitionRight.setFromX(rect.getTranslateX());
                translateTransitionRight.setToX(rect.getTranslateX()-30);
                translateTransitionRight.play();
            }               
        }
    });

}

在这里,当我连续按 LEFT/RIGHT 键时(即我没有松开键,我按住了几次),矩形会移动但不是连续的.它在动画开始后暂停一小段时间.暂停后动画继续流畅.

Here when I press either LEFT/RIGHT key continuously (i.e. I don't released the key, I hold it for some times) the rectangle moves but not continuously. It pauses for a small fraction of time just after animation started. After the pause the animation continues smoothly.

如何使用 KeyEvents 摆脱这种动画暂停?

How can I get rid of this pausing of animation with KeyEvents?

推荐答案

我会使用 AnimationTimer 来移动矩形,并且只更新一个表示按下键或释放键时速度的属性:

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);
    }
  }
});

更新:

AnimationTimer 每次执行一次其句柄方法JavaFX 机制渲染帧的时间.传入 handle 方法的 long 是渲染帧的时间戳,以纳秒为单位.

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.

这种工作方式是我们跟踪上次更新时间.handle(...) 方法计算自上次更新以来经过的时间,将其乘以矩形的速度,然后将矩形的 translateX 更新为该量.AnimationTimer 始终在运行,但最初速度设置为零,因此矩形不会移动.

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.

keyPressed 处理程序只是改变速度:如果向右移动则为正值,如果向左移动则为负值.keyReleased 处理程序将速度设置回零.

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.

这篇关于如何在javaFX中使用KeyPress事件获得流畅的动画?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆