gpt4 book ai didi

Javafx 时间线在经过多个监听器时停止播放

转载 作者:行者123 更新时间:2023-12-02 10:17:53 28 4
gpt4 key购买 nike

我是一个最近学习JavaFX的初学者,我一直在尝试制作一个程序,在单击节点时在节点上执行动画。我试图看看是否有其他人尝试过类似的事情,但我无法找到与我尝试做的事情类似的案例。

时间轴对 Pane 进行动画处理,其中包含水平穿过屏幕的矩形和文本,执行完成后舞台将更改场景。当用户单击按钮返回原始场景时,按钮应该执行另一个动画。

我已经验证不是场景转换导致它停止,并且我还验证了程序确实在时间轴上执行 .play()。时间线是在自定义监听器中执行的,因此据我所知,监听器不是问题。

这是重现我遇到的问题的代码示例,运行脚本并继续。在这里您可以看到 done 正在打印到 Main_Button_Animation.play(); 下面的控制台,但是没有任何动画。

import java.util.ArrayList;
import java.util.List;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

public class main extends Application{
Scene scene1;

@Override
public void start(Stage primaryStage) {

primaryStage.setTitle("test");
Main_Screen MainScreen = new Main_Screen(800, 480);

scene1 = MainScreen.MainScreen(primaryStage);
MainScreen.getInitiater().Calibration_Listener(() -> {
MainScreen.getInitiater().Back_Button_Pressed();
});

primaryStage.setScene(scene1);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
//custom listeners
interface Calibration {
void menu();
}
interface Back {
void back();
}
class Initiater {
private List<Calibration> calilist = new ArrayList<Calibration>();;
private List<Back> Go_Back = new ArrayList<Back>();

public void Calibration_Listener(Calibration toAdd) {
calilist.add(toAdd);
}
public void Back_Listener(Back toAdd) {
Go_Back.add(toAdd);
}

public void Calibration_Pressed() {
System.out.println("Calibration Pressed");
for (Calibration hl : calilist)
hl.menu();
}
public void Back_Button_Pressed() {
System.out.println("Back Pressed");
for (Back hl : Go_Back)
hl.back();
}
}

//animations and setup
class Main_Screen {
Initiater initiater;
private int X;
private int Y;

public Main_Screen(int X, int Y) {
this.initiater = new Initiater();
this.X = X;
this.Y = Y;
}

private Pane UI_Button(String name, int[] pos, int[] size, Color color) {
final Text text = new Text(0, 0, name);
text.setFont(new Font(20));

final Rectangle outline = new Rectangle(0, 0, size[0], size[1]);
outline.setFill(color);

final StackPane stack = new StackPane();
stack.getChildren().addAll(outline, text);
stack.setLayoutX(pos[0]);
stack.setLayoutY(pos[1]);

return stack;
}

public int getX() {
return this.X;
}

public int getY() {
return this.Y;
}

public Initiater getInitiater() {
return this.initiater;
}

public Scene MainScreen(Stage stage) {
Scene scene = new Scene(new Group(), getX(), getY());
scene.setFill(Color.WHITE);

Pane Start = UI_Button("Start", new int[] { getX() - getX() / 4, 0 }, new int[] { getX() / 4, getY() / 4 }, Color.rgb(255, 0, 0));
Pane Calibration = UI_Button("Callibration", new int[] { 0, ((getY() + (getY() / 8)) / 4) * 0 }, new int[] { getX() / 2, getY() / 4 }, Color.rgb(60, 208, 230));

System.out.println(Calibration.boundsInLocalProperty());
((Group) scene.getRoot()).getChildren().addAll(Calibration, Start);

final Timeline Main_Button_Animation = new Timeline();
final KeyFrame Cali_kf = new KeyFrame(Duration.millis(500), new KeyValue(Calibration.translateXProperty(), getX() / 2));
final KeyFrame Start_kf = new KeyFrame(Duration.millis(500), new KeyValue(Start.translateXProperty(), -getX() / 4));
Main_Button_Animation.getKeyFrames().addAll(Cali_kf, Start_kf);
Main_Button_Animation.setRate(-1);
Main_Button_Animation.jumpTo(Main_Button_Animation.getTotalDuration());
Main_Button_Animation.play();

Calibration.setOnMouseClicked(MouseEvent -> {
Calibration.setDisable(true);
Start.setDisable(true);
System.out.println(Calibration.boundsInLocalProperty());
Main_Button_Animation.setRate(1);
Main_Button_Animation.jumpTo(Duration.millis(0));
Main_Button_Animation.play();
Main_Button_Animation.setOnFinished(event -> {
Main_Button_Animation.play();
System.out.println("done");
});
});
return scene;
}

}

Edit1:为了清楚起见,上面的示例没有使用任何场景转换。这是一个场景转换的示例。

import java.util.ArrayList;
import java.util.List;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

public class main extends Application{
Scene scene1, scene2;

@Override
public void start(Stage primaryStage) {

primaryStage.setTitle("test");
Main_Screen MainScreen = new Main_Screen(800, 480);

scene1 = MainScreen.MainScreen(primaryStage);
MainScreen.getInitiater().Calibration_Listener(() -> {
primaryStage.setScene(scene2);
primaryStage.show();
});

Label label2 = new Label("This is the second scene");
Button button2 = new Button("Go to scene 1");
button2.setOnAction(e -> {
MainScreen.getInitiater().Back_Button_Pressed();
primaryStage.setScene(scene1);
primaryStage.show();
});
VBox layout2 = new VBox(20);
layout2.getChildren().addAll(label2, button2);
scene2 = new Scene(layout2, 800, 480);

primaryStage.setScene(scene1);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
//custom listeners
interface Calibration {
void menu();
}
interface Back {
void back();
}
class Initiater {
private List<Calibration> calilist = new ArrayList<Calibration>();;
private List<Back> Go_Back = new ArrayList<Back>();

public void Calibration_Listener(Calibration toAdd) {
calilist.add(toAdd);
}
public void Back_Listener(Back toAdd) {
Go_Back.add(toAdd);
}

public void Calibration_Pressed() {
System.out.println("Calibration Pressed");
for (Calibration hl : calilist)
hl.menu();
}
public void Back_Button_Pressed() {
System.out.println("Back Pressed");
for (Back hl : Go_Back)
hl.back();
}
}

//animations and setup
class Main_Screen {
Initiater initiater;
private int X;
private int Y;

public Main_Screen(int X, int Y) {
this.initiater = new Initiater();
this.X = X;
this.Y = Y;
}

private Pane UI_Button(String name, int[] pos, int[] size, Color color) {
final Text text = new Text(0, 0, name);
text.setFont(new Font(20));

final Rectangle outline = new Rectangle(0, 0, size[0], size[1]);
outline.setFill(color);

final StackPane stack = new StackPane();
stack.getChildren().addAll(outline, text);
stack.setLayoutX(pos[0]);
stack.setLayoutY(pos[1]);

return stack;
}

public int getX() {
return this.X;
}

public int getY() {
return this.Y;
}

public Initiater getInitiater() {
return this.initiater;
}

public Scene MainScreen(Stage stage) {
Scene scene = new Scene(new Group(), getX(), getY());
scene.setFill(Color.WHITE);

Pane Start = UI_Button("Start", new int[] { getX() - getX() / 4, 0 }, new int[] { getX() / 4, getY() / 4 }, Color.rgb(255, 0, 0));
Pane Calibration = UI_Button("Callibration", new int[] { 0, ((getY() + (getY() / 8)) / 4) * 0 }, new int[] { getX() / 2, getY() / 4 }, Color.rgb(60, 208, 230));

System.out.println(Calibration.boundsInLocalProperty());
((Group) scene.getRoot()).getChildren().addAll(Calibration, Start);

final Timeline Main_Button_Animation = new Timeline();
final KeyFrame Cali_kf = new KeyFrame(Duration.millis(500), new KeyValue(Calibration.translateXProperty(), getX() / 2));
final KeyFrame Start_kf = new KeyFrame(Duration.millis(500), new KeyValue(Start.translateXProperty(), -getX() / 4));
Main_Button_Animation.getKeyFrames().addAll(Cali_kf, Start_kf);
Main_Button_Animation.setRate(-1);
Main_Button_Animation.jumpTo(Main_Button_Animation.getTotalDuration());
Main_Button_Animation.play();

Calibration.setOnMouseClicked(MouseEvent -> {
Calibration.setDisable(true);
Start.setDisable(true);
System.out.println(Calibration.boundsInLocalProperty());
Main_Button_Animation.setRate(1);
Main_Button_Animation.jumpTo(Duration.millis(0));
Main_Button_Animation.play();
Main_Button_Animation.setOnFinished(event -> {
this.initiater.Calibration_Pressed();
System.out.println("done");
});
});
this.initiater.Back_Listener(() -> {
Main_Button_Animation.setRate(-1);
Main_Button_Animation.jumpTo(Main_Button_Animation.getTotalDuration());
Main_Button_Animation.play();
Main_Button_Animation.setOnFinished(e -> {
Calibration.setDisable(false);
Start.setDisable(false);
});
});
return scene;
}

}

最佳答案

您只需为 Timeline 动画末尾的帧定义 KeyValue。这只允许时间轴在动画开始时的值和目标值之间进行插值。在动画开头插入另一个 KeyFrame 应该可以解决此问题:

public Scene MainScreen(Stage stage) {
final Group root = new Group();

Scene scene = new Scene(root, getX(), getY());
scene.setFill(Color.WHITE);

Pane Start = UI_Button("Start", new int[] { getX() * 3 / 4, 0 }, new int[] { getX() / 4, getY() / 4 }, Color.RED);
Pane Calibration = UI_Button("Callibration", new int[] { 0, 0 }, new int[] { getX() / 2, getY() / 4 }, Color.rgb(60, 208, 230));

System.out.println(Calibration.boundsInLocalProperty());
root.getChildren().addAll(Calibration, Start);

final Timeline Main_Button_Animation = new Timeline(
new KeyFrame(Duration.ZERO,
new KeyValue(Calibration.translateXProperty(), 0),
new KeyValue(Start.translateXProperty(), 0)),
new KeyFrame(Duration.millis(500),
new KeyValue(Calibration.translateXProperty(), getX() / 2),
new KeyValue(Start.translateXProperty(), -getX() / 4)));

Main_Button_Animation.setRate(-1);
Main_Button_Animation.playFrom(Main_Button_Animation.getTotalDuration());

Calibration.setOnMouseClicked(MouseEvent -> {
Calibration.setDisable(true);
Start.setDisable(true);
System.out.println(Calibration.boundsInLocalProperty());
Main_Button_Animation.playFromStart();
Main_Button_Animation.setOnFinished(event -> {
this.initiater.Calibration_Pressed();
System.out.println("done");
});
});
this.initiater.Back_Listener(() -> {
Main_Button_Animation.setRate(-1);
Main_Button_Animation.playFrom(Main_Button_Animation.getTotalDuration());
Main_Button_Animation.setOnFinished(e -> {
Calibration.setDisable(false);
Start.setDisable(false);
});
});
return scene;
}

请注意,这里有一些额外的更改:

  • 同时将 KeyFrame 组合为具有多个 KeyValue 的单个帧
  • 保留对场景根的引用以避免使用 getter/cast
  • 使用 playFromplayFromStart 代替 jumpTo/play
  • 简化了传递给 UI_Button 方法的一些参数(但四舍五入可能会使结果相差 1)
  • ...

关于Javafx 时间线在经过多个监听器时停止播放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54544107/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com