java - JavaFX在for循环中将节点添加到锚窗格,但每次迭代等待几秒钟,然后再添加下一个节点
问题描述
我正在制作一个游戏,应该发生的是,在一个 for 循环中,同时迭代一个数组列表。在每个循环中,我想将一个节点添加到我的场景中,然后我想等待一段时间并将另一个节点添加到场景中。每次迭代之间的时间也在arraylist的项目中定义,并且每次迭代可以不同。
我试过的:
//Circle is my own class, other than these attributes along with getters it has nothing in it.
//The last number is the time to wait.
//Also for testing i used a static arraylist, normally the items come from a json file.
ArrayList<Circle> lvlNodes = new ArrayList<>();
lvlNodes.add(new Circle(50,50, Color.RED,250,100));
lvlNodes.add(new Circle(200,100, Color.BLUE,500,250));
lvlNodes.add(new Circle(900,500, Color.YELLOW,750,500));
lvlNodes.add(new Circle(400,50, Color.GREEN,1000,500));
//Iterating over the arraylist and adding the nodes.
for (int i=0; i<lvlNodes.size(); i++) {
Circle currentNode = lvlNodes.get(i);
//Add the node the the anchor pane.
view.addLvlNode(currentNode, diameter); //diameter is a final value, all nodes in the game are the same and thus only added once at the top of the json file
//Wait and move on to the next one.
try {
Thread.sleep(currentNode.getTimeToNextNode())
} catch (InterruptedException e) {
System.out.println(e);
}
}
//Adds the next node to the game.
public void addLvlNode(Circle circle, double diameter) {
//Create node.
javafx.scene.shape.Circle lvlNode = new javafx.scene.shape.Circle(circle.getPosX(),
circle.getPosY(), diameter/2);
//Anchor node the the anchorpane.
AnchorPane.setTopAnchor(lvlNode, (double)circle.getPosY());
AnchorPane.setLeftAnchor(lvlNode, (double)circle.getPosX());
anchrLevel.getChildren().add(lvlNode);
lvlNode.toBack();
}//addLvlNode.
Thread.sleep() 有效,for 循环中的每次迭代都包含中间的时间。但是在 for 循环完成迭代之前不会添加节点。
有没有办法在 for 循环中添加节点,中间有时间量?
解决方案
您遇到的问题是您的所有代码都在 FXAT 上运行,而当 FXAT 忙于运行该代码时,它无法执行更新屏幕以实际添加圆圈等操作。因此,当您的代码完成时,包括所有 Thread.sleep() 调用,它会同时完成所有屏幕绘制。
我没有构建您的自定义 Circle 类,而是构建了一些数组来保存 Circles 和等待时间。然后我将 addLvlNode & sleep 放入后台作业。后台作业使用 Platform.runLater() 将节点添加到 FXAT 的窗格中:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import java.util.ArrayList;
public class CircleMaker extends Application {
private Pane mainPain;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
ArrayList<Circle> circles = new ArrayList<>();
ArrayList<Integer> waitTimes = new ArrayList<>();
circles.add(new Circle(50, 50, 125, Color.RED));
waitTimes.add(1000);
circles.add(new Circle(200, 200, 250, Color.BLUE));
waitTimes.add(2500);
circles.add(new Circle(900, 500, 375, Color.YELLOW));
waitTimes.add(5000);
circles.add(new Circle(400, 50, 500, Color.GREEN));
waitTimes.add(5000);
Thread waitingThread = new Thread(() -> {
for (int idx = 0; idx < 4; idx++) {
Circle thisCircle = circles.get(idx);
Platform.runLater(() -> addLvlNode(thisCircle));
try {
Thread.sleep(waitTimes.get(idx));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
mainPain = new Pane();
primaryStage.setScene(new Scene(mainPain, 1000, 800));
primaryStage.show();
waitingThread.start();
}
private void addLvlNode(Node circle) {
mainPain.getChildren().add(circle);
circle.toBack();
}
}
我还将等待时间延长了 10 倍,以便更容易看到每个圆圈都是轮流绘制的,它们之间有一个暂停。
您可能可以使用 Timeline 来执行此操作,但是由于您说 Circle 数据最终将是来自外部源的 JSON,这对我来说意味着您可能已经发生了某种非 JavaFX 机制,所以这可能是最好的只使用后台线程来做你需要的任何事情。您可以从这个示例中看到基本框架是什么。
推荐阅读
- embedded-linux - U-Boot如何找到内核?是否需要知道确切的地址
- postgresql - Hibernate InsertQuery 不会在 Postgres 上生成身份
- asp.net-core - 我是否需要为每个许可(索赔)制定政策?
- python - python + tornado:导入请求处理程序上的 404
- python - 使用 rpy2 导入和使用 R 'heavy' 包
- c++ - C++ 访问向量超出 size() 且低于 capacity()
- sql - 如何将天数转换为周数和天数
- shopify - 显示 shopify 库存库存位置
- format - 如何在 Lisp 中将 0 添加到整数列表中
- sql - 试图在一个表上查找两个日期之间的记录和另一个表上的一些信息