JavaFX - 使多个对象上的Timeline对象执行一次EventHandler
JavaFX - making Timeline object on multiple objects execute EventHandler once
我现在正在使用 JavaFX,遇到了 运行 问题。我创建了一个简单示例来演示我面临的问题。
我的问题是,我在多个匿名 Circle
对象上设置了一个 Timeline
对象,我希望在时间轴完成其 play()
方法后发生一个动作。为此,我设置了一个 setOnFinished
事件处理程序以在动画播放完毕后执行某些操作,但是,它会多次执行此逻辑,因为它正在处理多个对象。
这里我有一个简单的程序,可以将 3 个匿名对象添加到 VBox
并且有一个按钮将调用 flash()
方法在圆圈上启动时间轴动画。
package sample;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
VBox root = new VBox();
VBox circles = new VBox();
Button btn = new Button("Touch me to make me flash ;)");
btn.setOnAction(e -> flash(circles));
for(int i = 0; i < 3; i++) {
circles.getChildren().add(new Circle(25, Color.RED));
}
circles.setSpacing(10);
circles.setAlignment(Pos.CENTER);
root.getChildren().addAll(circles, btn);
root.setSpacing(10);
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root, 500, 500));
primaryStage.show();
}
private void flash(VBox root) {
for(Node circle : root.getChildren()) {
final Circle c = (Circle) circle;
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(0.5), e -> c.setFill(Color.GOLD)),
new KeyFrame(Duration.seconds(1.0), e -> c.setFill(Color.RED))
);
timeline.setCycleCount(5);
timeline.play();
timeline.setOnFinished(e -> System.out.println("Do something here"));
}
}
}
在flash()
方法中可以看到有一个EventHandler执行这行代码:
System.out.println("Do something here")
我希望它只执行一次,但它执行了 3 次,因为 Timeline 对象设置在 3 个圆圈上。
如何才能让 EventHandler 只执行一次?
考虑对所有 Circle
个对象使用一个 TimeLine
个对象:
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application {
private ObjectProperty<Paint> colorProperty;
@Override
public void start(Stage primaryStage) throws Exception{
colorProperty = new SimpleObjectProperty<>(Color.WHITE);
VBox root = new VBox();
VBox circles = new VBox();
Button btn = new Button("Touch me to make me flash ;)");
btn.setOnAction(e -> flash(circles));
for(int i = 0; i < 3; i++) {
circles.getChildren().add(new Circle(25, Color.RED));
}
circles.setSpacing(10);
circles.setAlignment(Pos.CENTER);
root.getChildren().addAll(circles, btn);
root.setSpacing(10);
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root, 500, 500));
primaryStage.show();
}
private void flash(VBox root) {
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(0.5), e -> colorProperty.set(Color.GOLD)),
new KeyFrame(Duration.seconds(1.0), e -> colorProperty.set(Color.RED))
);
timeline.setCycleCount(5);
timeline.play();
timeline.setOnFinished(e -> System.out.println("Do something here"));
for(Node circle : root.getChildren()) {
final Circle c = (Circle) circle;
c.fillProperty().bind(colorProperty);
}
}
public static void main(String[] args) {
launch(null);
}
}
我现在正在使用 JavaFX,遇到了 运行 问题。我创建了一个简单示例来演示我面临的问题。
我的问题是,我在多个匿名 Circle
对象上设置了一个 Timeline
对象,我希望在时间轴完成其 play()
方法后发生一个动作。为此,我设置了一个 setOnFinished
事件处理程序以在动画播放完毕后执行某些操作,但是,它会多次执行此逻辑,因为它正在处理多个对象。
这里我有一个简单的程序,可以将 3 个匿名对象添加到 VBox
并且有一个按钮将调用 flash()
方法在圆圈上启动时间轴动画。
package sample;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
VBox root = new VBox();
VBox circles = new VBox();
Button btn = new Button("Touch me to make me flash ;)");
btn.setOnAction(e -> flash(circles));
for(int i = 0; i < 3; i++) {
circles.getChildren().add(new Circle(25, Color.RED));
}
circles.setSpacing(10);
circles.setAlignment(Pos.CENTER);
root.getChildren().addAll(circles, btn);
root.setSpacing(10);
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root, 500, 500));
primaryStage.show();
}
private void flash(VBox root) {
for(Node circle : root.getChildren()) {
final Circle c = (Circle) circle;
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(0.5), e -> c.setFill(Color.GOLD)),
new KeyFrame(Duration.seconds(1.0), e -> c.setFill(Color.RED))
);
timeline.setCycleCount(5);
timeline.play();
timeline.setOnFinished(e -> System.out.println("Do something here"));
}
}
}
在flash()
方法中可以看到有一个EventHandler执行这行代码:
System.out.println("Do something here")
我希望它只执行一次,但它执行了 3 次,因为 Timeline 对象设置在 3 个圆圈上。
如何才能让 EventHandler 只执行一次?
考虑对所有 Circle
个对象使用一个 TimeLine
个对象:
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application {
private ObjectProperty<Paint> colorProperty;
@Override
public void start(Stage primaryStage) throws Exception{
colorProperty = new SimpleObjectProperty<>(Color.WHITE);
VBox root = new VBox();
VBox circles = new VBox();
Button btn = new Button("Touch me to make me flash ;)");
btn.setOnAction(e -> flash(circles));
for(int i = 0; i < 3; i++) {
circles.getChildren().add(new Circle(25, Color.RED));
}
circles.setSpacing(10);
circles.setAlignment(Pos.CENTER);
root.getChildren().addAll(circles, btn);
root.setSpacing(10);
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root, 500, 500));
primaryStage.show();
}
private void flash(VBox root) {
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(0.5), e -> colorProperty.set(Color.GOLD)),
new KeyFrame(Duration.seconds(1.0), e -> colorProperty.set(Color.RED))
);
timeline.setCycleCount(5);
timeline.play();
timeline.setOnFinished(e -> System.out.println("Do something here"));
for(Node circle : root.getChildren()) {
final Circle c = (Circle) circle;
c.fillProperty().bind(colorProperty);
}
}
public static void main(String[] args) {
launch(null);
}
}