我正在使用JavaFX创建一个Java应用程序,它能够将TranslateTransition应用于通用节点并连续调用它。 我从此网址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类:
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()方法中使用了一个Thread,但是在转换中我仍然有一个连续的延迟。 这是进行转换的最佳方式吗?我可以改进我的代码吗?
非常感谢您的支持。
答案 0 :(得分: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自动呈现更新的过渡帧。
如果在您使用的基础工具中已经表示了相同的值,我建议不要跟踪类中的属性。
例如:
int reverse = 1;
替换为transition.setAutoReverse(true)
或transition.setRate(1)
(或-1)。animated
替换为transition.getStatus()
。double positionY
,设置过渡的toY
。我不建议调用你的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中封装节点和转换,而不是其他字段,除非您需要在您的问题中不明显且尚未由Node或Transition提供的其他功能。如果你有这个额外的功能,那么你可以增强上面的AnimationControl类来添加它。
公开节点和转换过渡就足够了,好像用户想要管理动画一样,例如启动和停止它,然后用户可以从AnimationControl类中获取它。根据您的使用情况,整个AnimationControl类可能是不必要的,因为您可能不需要它提供的封装,而可能更喜欢直接使用节点和转换(如示例中演示的那样)。