【发布时间】:2020-11-21 05:59:38
【问题描述】:
下面的测试程序重现了这个问题。我理解抛出异常的原因,但我想知道如何解决它或在 JavaFX 中使用不同的构造来获得我想要的。
完整的应用程序是一个机器人模拟器,其中包含多个机器人,这些机器人可以自主、独立并同时在一个场地周围移动。每个机器人都有自己的 SequentialTransition 用于其特定的一组动作。该程序将 SequentialTransitions 添加到 ParallelTransition,然后播放。一切都很好,直到我设置了一个监听器,它会注意到机器人是否遇到了障碍物。我已将测试程序中的碰撞检测简化为仅适用于一个机器人和一堵墙。错误点标有 //** BROKEN!!下一行出现 IllegalStateException。
我真的想为遇到障碍物的机器人停止 SequentialTransition,但让其他机器人继续。我该怎么做?
该错误出现在 Java 8 中,但也出现在 Java 11 和 JavaFX 15 中。
package sample;
import javafx.animation.ParallelTransition;
import javafx.animation.SequentialTransition;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application {
private static final double FIELD_WIDTH = 600;
private static final double FIELD_HEIGHT = 600;
private Pane field = new Pane();
ParallelTransition parallel = new ParallelTransition();
SequentialTransition sequentialRobot1 = new SequentialTransition();
SequentialTransition sequentialRobot2 = new SequentialTransition();
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
// Place one field boundary for testing.
Line northBoundary = new Line(0, 0, FIELD_WIDTH, 0);
northBoundary.setStrokeWidth(5.0);
field.getChildren().add(northBoundary);
// Place the robots on the field.
// The first robot.
Rectangle robotBody1 = new Rectangle(100, 300, 60, 60);
robotBody1.setArcHeight(15);
robotBody1.setArcWidth(15);
robotBody1.setStroke(Color.BLACK);
robotBody1.setFill(Color.CRIMSON);
field.getChildren().add(robotBody1);
robotBody1.boundsInParentProperty().addListener((observable, oldValue, newValue) -> {
if (northBoundary.getBoundsInParent().intersects(robotBody1.getBoundsInParent())) {
//** BROKEN!! IllegalStateException on next line
sequentialRobot1.stop();
System.out.println("Collision detected");
parallel.play();
}
});
TranslateTransition translateTransition1 = new TranslateTransition();
translateTransition1.setNode(robotBody1);
translateTransition1.setByX(0);
translateTransition1.setByY(-300);
translateTransition1.setDuration(Duration.seconds(1));
translateTransition1.setOnFinished(event -> {
robotBody1.setLayoutX(robotBody1.getLayoutX() + robotBody1.getTranslateX());
robotBody1.setLayoutY(robotBody1.getLayoutY() + robotBody1.getTranslateY());
robotBody1.setTranslateX(0);
robotBody1.setTranslateY(0);
});
sequentialRobot1.getChildren().add(translateTransition1);
// The second robot.
Rectangle robotBody2 = new Rectangle(300, 300, 60, 60);
robotBody2.setArcHeight(15);
robotBody2.setArcWidth(15);
robotBody2.setStroke(Color.BLACK);
robotBody2.setFill(Color.CYAN);
field.getChildren().add(robotBody2);
TranslateTransition translateTransition2 = new TranslateTransition();
translateTransition2.setNode(robotBody2);
translateTransition2.setByX(0);
translateTransition2.setByY(-100);
translateTransition2.setDuration(Duration.seconds(1));
translateTransition2.setOnFinished(event -> {
robotBody2.setLayoutX(robotBody2.getLayoutX() + robotBody2.getTranslateX());
robotBody2.setLayoutY(robotBody2.getLayoutY() + robotBody2.getTranslateY());
robotBody2.setTranslateX(0);
robotBody2.setTranslateY(0);
});
sequentialRobot2.getChildren().add(translateTransition2);
parallel.getChildren().addAll(sequentialRobot1, sequentialRobot2);
parallel.play();
primaryStage.setTitle("Field");
primaryStage.setScene(new Scene(field, FIELD_WIDTH, FIELD_HEIGHT, Color.GRAY));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
【问题讨论】:
-
您似乎对如何实现您想要做的事情感到困惑。
Transitions、Sequentials和Parallel的工作方式似乎不合逻辑。 -
使用单个
AnimationTimer来更新每个机器人每次调用的位置可能更有意义。如果机器人遇到障碍物,请不要移动该机器人。 -
要使您的代码minimal reproducible example 添加fxml 文件或更好地以编程方式定义
root
标签: javafx