如何在JavaFX中创建连续的TranslateTransition
我正在使用JavaFX创建一个Java应用程序,它能够将TranslateTransition应用到一个通用节点并不断地调用它。 我从此url检索到一个简单的右箭头: 并使用它创建要转换的节点。 这是我的AnimatedNode类:如何在JavaFX中创建连续的TranslateTransition,java,animation,javafx,delay,transitions,Java,Animation,Javafx,Delay,Transitions,我正在使用JavaFX创建一个Java应用程序,它能够将TranslateTransition应用到一个通用节点并不断地调用它。 我从此url检索到一个简单的右箭头: 并使用它创建要转换的节点。 这是我的AnimatedNode类: package application.model.utils.addon; import javafx.animation.TranslateTransition; import javafx.scene.Node; import javafx.util.Dur
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;
}
}
这是应用程序类
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);
}
}
封装测试;
导入application.model.utils.addon.AnimatedNode;
导入javafx.application.application;
导入javafx.event.EventHandler;
导入javafx.scene.scene;
导入javafx.scene.image.image;
导入javafx.scene.image.ImageView;
导入javafx.scene.input.MouseButton;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.layout.BorderPane;
导入javafx.scene.layout.Pane;
导入javafx.stage.stage;
公共类测试扩展了应用程序{
私有最终字符串TITLE=“测试应用程序”;
专用最终双宽度=600;
私人最终双倍高度=400;
私有最终字符串ARROW\u PATH=“file:resources/png/ARROW.png”;
私有边界窗格根窗格;
@凌驾
公共无效开始(阶段primaryStage){
初级阶段。设置标题(标题);
rootPane=newborderpane();
rootPane.setPrefSize(宽度、高度);
图像=新图像(箭头\路径);
ImageView ImageView=新的ImageView(图像);
imageView.setFitWidth(宽度);
imageView.setFitHeight(高度);
imageView.setPreserveRatio(真);
AnimatedNode AnimatedNode=新的AnimatedNode(imageView,0.7);
窗格=新窗格();
pane.getChildren().add(animatedNode.getNode());
setOnMouseClicked(新的EventHandler(){
@凌驾
公共无效句柄(MouseEvent arg0){
if(arg0.getButton().equals(MouseButton.PRIMARY))
animatedNode.play();
if(arg0.getButton().equals(MouseButton.SECONDARY))
animatedNode.stop();
}
});
根窗格。设置中心(窗格);
场景=新场景(根窗格、宽度、高度);
初级阶段。场景(场景);
primaryStage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
}
将节点添加到通用窗格中;窗格上有一个鼠标听筒。我可以使用鼠标的主按钮启动TranslateTransition,然后使用第二个按钮停止它。
我在AnimatedNode的play()方法中使用了一个线程,但在转换过程中仍然有一个连续的延迟。
这是执行转换的最佳方式吗?我可以改进我的代码吗
非常感谢您的支持。示例
这是一个简化的示例,演示了通过鼠标左键和右键单击开始和停止的连续动画
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将自动渲染更新的转换帧
我不建议跟踪类中的属性,因为在您使用的底层工具中已经表示了相同的值
例如:
- 替换
int reverse=1代码>带有或(或-1)
- 将动画的替换为
- 设置转换的位置,而不是双位置
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类可能是不必要的,因为您可能不需要它提供的封装,而是更愿意直接使用节点和转换(如示例中演示的)。非常感谢您的帮助!如您所见,我不知道转换类的方法,所以我试图自己实现一个无限循环。你的方法显然是最好的。