2014-01-24 87 views
2

我正在嘗試在JavaFX中實現矩形形狀的左右運動。下面是我的代碼:如何使用javaFX中的KeyPress事件獲得流暢的動畫?

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

} 

這裏當我按下要麼左/右鍵連續(即我不釋放的鍵,我認爲它的一些倍)的矩形移動,但不會持續。動畫開始後,它暫停一小部分時間。暫停後,動畫繼續順利進行。

我怎樣才能擺脫這種暫停使用的KeyEvents動畫的?

回答

4

我會用一個AnimationTimer用於移動矩形,只是更新表示釋放鍵按下或鍵的速度的屬性:

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:

AnimationTimer一次執行它的把手的方法,每個JavaFX機制呈現一幀時間。長處傳遞給句柄方法是渲染幀的時間戳,以納秒爲單位。

這種工作方式是,我們跟蹤的最後更新時間。 handle(...)方法計算自上次更新以來的經過時間,將其乘以矩形的速度,並將該矩形的translateX更新爲該量。 AnimationTimer始終運行,但最初速度設置爲零,因此矩形不會移動。如果向右移動,並且如果向左移動負值到正值:

的的keyPressed處理程序僅改變速度。 keyReleased處理程序將速度設置爲零。

+0

這種方法的一個很好的(但也許不明顯)功能是,您可以對矩形的速度進行完整的程序控制;它不是由操作系統級別的設置決定的,如鍵盤重複速率等。 –

+0

嗨,詹姆斯,當我快速按下左/右鍵時,動畫開始時仍有一些暫停效果。你也可以提供一些關於你在這裏實現的邏輯的解釋。 – Angom

+0

通過一些分析我可以理解邏輯。此外,我還在scene.setOnKeyReleased()中做了小的修改,只有當左/右鍵都釋放時,纔將rectangleVelocity設置爲0,否則會導致動畫中的暫停效果。謝謝。 – Angom