2017-04-04 3 views
0

私はJavaFXを使って、TranslateTransitionをジェネリックノードに適用してそれを連続的に呼び出すことができるJavaアプリケーションを作成しています。 私はこのURLから単純な右矢印を取得しましたhttps://www.google.it/search?q=arrow.png&espv=2&source=lnms&tbm=isch&sa=X&ved=0ahUKEwiGheeJvYrTAhWMB5oKHU3-DxgQ_AUIBigB&biw=1600&bih=764#imgrc=rH0TbMkQY2kUaM: そしてそれを使って翻訳するノードを作成しました。 これは私のAnimatedNodeクラスです:JavaFXで連続​​的なTranslateTransitionを作成するには

package application.model.utils.addon; 

import javafx.animation.TranslateTransition; 
import javafx.scene.Node; 
import javafx.util.Duration; 

public class AnimatedNode { 

    private Node node; 
    private double positionY; 
    private TranslateTransition translateTransition; 
    private boolean animated; 

    private int reverse = 1; 

    public AnimatedNode(Node node, double animationTime) { 
     setPositionY(0.0); 
     setNode(node); 
     setTranslateTransition(animationTime); 
    } 

    public void play() { 
     if(translateTransition != null && !isAnimated()) { 

      setAnimated(true); 

      new Thread() { 
       @Override 
       public void run() { 
        while(isAnimated()) { 
         translateTransition.setToY(positionY + 50 * reverse); 
         translateTransition.play(); 

         reverse = -reverse; 
         setPositionY(translateTransition.getToY()); 
        } 
       } 
      }.start(); 
     } 
    } 

    public void stop() { 
     setAnimated(false); 
    } 

    public Node getNode() { 
     return node; 
    } 

    private void setNode(Node node) { 
     this.node = node; 
    } 

    public TranslateTransition getTranslateTransition() { 
     return translateTransition; 
    } 

    private void setTranslateTransition(double animationTime) { 
     translateTransition = new TranslateTransition(); 

     if(node != null) { 
      translateTransition.setDuration(Duration.seconds(animationTime)); 
      translateTransition.setNode(node); 
     } 
    } 

    public double getPositionY() { 
     return positionY; 
    } 

    private void setPositionY(double positionY) { 
     this.positionY = positionY; 
    } 

    public boolean isAnimated() { 
     return animated; 
    } 

    private void setAnimated(boolean animated) { 
     this.animated = animated; 
    } 
} 

、これはApplicationクラス

package test; 

import application.model.utils.addon.AnimatedNode; 
import javafx.application.Application; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.image.Image; 
import javafx.scene.image.ImageView; 
import javafx.scene.input.MouseButton; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.Pane; 
import javafx.stage.Stage; 

public class Test extends Application { 

    private final String TITLE = "Test application"; 
    private final double WIDTH = 600; 
    private final double HEIGHT = 400; 
    private final String ARROW_PATH = "file:resources/png/arrow.png"; 

    private BorderPane rootPane; 

    @Override 
    public void start(Stage primaryStage) { 
     primaryStage.setTitle(TITLE); 

     rootPane = new BorderPane(); 
     rootPane.setPrefSize(WIDTH, HEIGHT); 

     Image image = new Image(ARROW_PATH); 
     ImageView imageView = new ImageView(image); 
     imageView.setFitWidth(WIDTH); 
     imageView.setFitHeight(HEIGHT); 
     imageView.setPreserveRatio(true); 
     AnimatedNode animatedNode = new AnimatedNode(imageView, 0.7); 

     Pane pane = new Pane(); 
     pane.getChildren().add(animatedNode.getNode()); 

     pane.setOnMouseClicked(new EventHandler<MouseEvent>() { 
      @Override 
      public void handle(MouseEvent arg0) { 
       if(arg0.getButton().equals(MouseButton.PRIMARY)) 
        animatedNode.play(); 

       if(arg0.getButton().equals(MouseButton.SECONDARY)) 
        animatedNode.stop(); 
      } 
     }); 

     rootPane.setCenter(pane); 
     Scene scene = new Scene(rootPane, WIDTH, HEIGHT); 

     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

ノードは、一般的なペインに追加されています。ペインにはMouseListenerがあります。私は、マウスのプライマリボタンを使ってTranslateTransitionを開始し、セカンダリボタンでそれを止めることができます。 私はAnimatedNodeのplay()メソッドでスレッドを使用しましたが、遷移にはまだ遅延があります。 これは移行を実行する最善の方法ですか?コードを改善することはできますか?

ご協力いただきありがとうございます。

答えて

0

サンプル

これは、連続的なアニメーションを開始し、左と右のマウスクリックによって停止示して簡略化した例です。

import javafx.animation.*; 
import javafx.application.Application; 
import javafx.scene.Scene; 
import javafx.scene.image.*; 
import javafx.scene.layout.Pane; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class BouncingCat extends Application {  
    private static final double WIDTH = 100; 
    private static final double HEIGHT = 100; 
    private final String ARROW_PATH = 
      "http://icons.iconarchive.com/icons/iconka/meow-2/64/cat-rascal-icon.png"; 
      // image source: http://www.iconka.com 

    @Override 
    public void start(Stage stage) { 
     Image image = new Image(ARROW_PATH); 
     ImageView imageView = new ImageView(image); 
     TranslateTransition animation = new TranslateTransition(
       Duration.seconds(0.7), imageView 
     ); 
     animation.setCycleCount(Animation.INDEFINITE); 
     animation.setFromY(0); 
     animation.setToY(50); 
     animation.setAutoReverse(true); 

     Pane pane = new Pane(imageView); 
     Scene scene = new Scene(pane, WIDTH, HEIGHT); 

     scene.setOnMouseClicked(e -> { 
      switch (e.getButton()) { 
       case PRIMARY: 
        animation.play(); 
        break; 

       case SECONDARY: 
        animation.pause(); 
        break; 
      } 
     }); 

     stage.setScene(scene); 
     stage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

アドバイス

トランジションを持っているときは、スレッドを必要としません。 JavaFXは、更新されたトランジションフレームをそれぞれ自動的にレンダリングします。pulse

クラス内のプロパティを追跡することはお勧めしません。これらの値は、使用する基礎となるツールで既に表されています。例えば

ノードを拡張しない限り、AnimatedNodeクラスを呼び出すことはお勧めできません。それ以外の場合は、混乱させる代わりにAnimationControlなどと呼んでください。

import javafx.animation.TranslateTransition; 
import javafx.scene.Node; 
import javafx.util.Duration; 

public class AnimationControl { 
    private final TranslateTransition translateTransition; 

    public AnimationControl(Duration duration, Node node) { 
     translateTransition = new TranslateTransition(duration, node); 
    } 

    public TranslateTransition getTranslateTransition() { 
     return translateTransition; 
    } 
} 

あなただけがあなたの質問で明らかにならないと、すでにノードまたは遷移によって提供されていない更なる機能を必要としない限り、ノードとAnimationControlおよびその他のない分野の変遷をカプセル化する必要があります。その余分な機能がある場合は、上記のAnimationControlクラスを拡張して追加することができます。

アニメーションを管理したいと思っているように、アニメーションを開始したり停止したりするのと同じように、ノードと翻訳トランジションを公開するだけで十分です。ユーザーはAnimationControlクラスから取得できます。あなたのユースケースによっては、AnimationControlクラス全体が必要でないかもしれないので、AnimationControlクラス全体が不要になるかもしれません。代わりに、ノードとトランジション(サンプルでデモされたもの)で直接作業する方が好きかもしれません。

+0

ありがとうございました!ご覧のように、私はTransitionクラスのメソッドを知らなかったので、無限ループを自分で実現しようとしました。あなたのアプローチは明らかに最高です。 – Giordano

関連する問題