I'm trying to write a code that will simulate sand pile, and I would like to open new window with simulation in another thread. In this case I have to dynamically change view of the 2nd window, but the view waits until the simulate()
method ends even if it is run in another thread. What can I do to change view in SandPileApplicationSimulation:run()
method body?
Controller class - simulation method:
public class SandPileController {
@FXML
public TextField interval;
@FXML
public TextField pathToBoard;
@FXML
public ChoiceBox<String> sandGenerationMode;
@FXML
protected void simulate() {
// you can ignore that 3 lines
FieldRoleFileParser parser = new FieldRoleFileParser();
FieldRole[][] fieldRoles = parser.parse(pathToBoard.getText());
String value = sandGenerationMode.getValue();
// this construtor is running initializeView method and it is creating new Stage
SandPileApplicationSimulation sandPileApplicationSimulation = new SandPileApplicationSimulation(fieldRoles,
Double.parseDouble(interval.getText()),
SandGenerationMode.valueOf(value));
Thread thread = new Thread(sandPileApplicationSimulation);
thread.start();
}
}
Stage view:
private void initializeView(FieldRole[][] values) {
Stage stage = new Stage();
GridPane root = new GridPane();
//this loops generates some rectangles based on input
for (int i = 0; i < columnCount; i++) {
for (int j = 0; j < columnLength; j++) {
FieldRole fieldRole = values[i][j];
Rectangle square = new Rectangle(50, 50);
square.setFill(fieldRole.getColor());
root.add(square, i, j);
board[i][j] = new Field(fieldRole, square);
}
}
stage.setScene(new Scene(root));
stage.show();
}
run() method (from Runnable) in SandPileApplicationSimulation class - the method wherein I would like to change the view of scene:
@Override
@SneakyThrows
public void run() {
boolean simulationMode = true;
boolean hasAnyChange = true;
generateSand(); // <-- this method change the color of some rectangles
while (hasAnyChange) {
hasAnyChange = false;
Thread.sleep(interval);
hasAnyChange = simulateFrame(simulationMode); // <-- this lane should change the view by changing the color of rectangles
simulationMode = !simulationMode;
generateSand();
}
}
I tried to write only the important information; if I forget something, just tell me please. Thanks for your answers.
EDIT: Here is also main application class and fxml file (only main app has it) class:
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(SandPileApplication.class.getResource("view.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 320, 175);
stage.setTitle("Sand pile simulation");
stage.resizableProperty()
.setValue(false);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
fxml
<VBox alignment="CENTER" spacing="20.0" xmlns:fx="http://javafx.com/fxml"
fx:controller="pl.umcs.sandpilesimulator.SandPileController">
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/>
</padding>
<TextField fx:id="interval">1.0</TextField>
<TextField fx:id="pathToBoard" promptText="Path to file with board..."/>
<ChoiceBox fx:id="sandGenerationMode">
<items>
<FXCollections fx:factory="observableArrayList">
<String fx:value="CENTER" />
<String fx:value="RANDOM" />
</FXCollections>
</items>
</ChoiceBox>
<Button text="Simulate" onAction="#simulate"/>
</VBox>