There is a lot of code in this question, and I don’t think you need all this to solve the concepts that you are really asking about. Therefore, I will simply give a high level of response here. If you want to change your question to something much simpler with regard to the actual problem, then I can make it specific to this example.
I would probably try to do this without threads, but using the animation API. For example, you can use Timelinewith the following main circuit:
public class Controller {
private Timeline timeline ;
@FXML
public void initialize() {
timeline = new Timeline(new KeyFrame(Duration.seconds(100)), e -> {
if (moreStepsToDo()) {
doNextStep();
} else {
stopSimulation();
}
});
timeline.setCycleCount(Animation.INDEFINITE);
}
private boolean moreStepsToDo() {
}
private void doNextStep() {
}
@FXML
private void stopSimulation() {
timeline.stop();
}
@FXML
private void pauseSimulation() {
timeline.pause();
}
@FXML
private void playSimulation() {
timeline.play();
}
@FXML
private void resetSimulation() {
timeline.jumpTo(Duration.ZERO);
}
}
, : FX, , . , . API- pause(), play() stop() , ; .
, ( , , vbox ).
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class SimplePausableAnimation extends Application {
private VBox left;
private VBox right;
private Timeline timeline;
private Button pausePlay;
@Override
public void start(Stage primaryStage) {
left = new VBox(10);
left.setMinWidth(200);
right = new VBox(10);
right.setMinWidth(200);
HBox hbox = new HBox(10, left, right);
pausePlay = new Button();
Button reset = new Button("Reset");
reset.setOnAction(e -> reset());
reset();
BorderPane root = new BorderPane(hbox);
HBox buttons = new HBox(5, pausePlay, reset);
buttons.setAlignment(Pos.CENTER);
root.setBottom(buttons);
Scene scene = new Scene(root, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private void reset() {
if (timeline != null) {
timeline.stop();
}
left.getChildren().clear();
right.getChildren().clear();
for (int i = 0; i < 5; i++) {
left.getChildren().add(new Rectangle(100, 100, Color.CORNFLOWERBLUE));
}
timeline = new Timeline(new KeyFrame(Duration.seconds(1), e -> {
if (moreStepsToDo()) {
doNextStep();
} else {
timeline.stop();
}
}));
timeline.setCycleCount(Animation.INDEFINITE);
pausePlay.disableProperty().bind(Bindings.createBooleanBinding(() -> {
if (left.getChildren().isEmpty()) {
return true;
}
return false;
}, left.getChildren()));
pausePlay.textProperty().bind(Bindings.createStringBinding(() -> {
if (timeline.getStatus() == Animation.Status.RUNNING) {
return "Pause";
}
return "Play";
}, timeline.statusProperty()));
pausePlay.setOnAction(e -> {
if (timeline.getStatus() == Animation.Status.RUNNING) {
timeline.pause();
} else {
timeline.play();
}
});
}
private boolean moreStepsToDo() {
return !left.getChildren().isEmpty();
}
private void doNextStep() {
int n = left.getChildren().size();
Node node = left.getChildren().remove(n - 1);
right.getChildren().add(node);
}
public static void main(String[] args) {
launch(args);
}
}
, - Semaphore , :
Semaphore pauser = new Semaphore(1);
Thread simulationThread = new Thread(() -> {
try {
while (! Thread.currentThread().isInterrupted()) {
pauser.acquire();
// do simulation step
pauser.release();
Thread.sleep(100);
}
} catch (InterruptedException exc) {
// ignore and exit thread...
}
});
(, Task, .)
pauser.acquire(); ( ), pauser.release(), , .