Afunakwa
Afunakwa

Reputation: 437

Update scene along with thread

I'm trying to have a scene progressively display the changes done to an instance of a class that I update regularly within a thread.

So far I have

 public void start(Stage primaryStage) {   
    Environment env = new Environment(10, 10);
    StackPane layout = new StackPane();

    primaryStage.setTitle("Vacuum World");
    Button btn = new Button();
    btn.setText("Start");

    Text text = new Text();

    btn.setOnAction(new EventHandler<ActionEvent>() {
        public void handle(ActionEvent event) {
            Thread t = new updateThread(env, text);
            t.run();
        }
    });

    layout.getChildren().add(btn);
    layout.getChildren().add(text); 
    primaryStage.setScene(new Scene(layout));
    primaryStage.show();
}

and the thread in question:

public class updateThread extends Thread {
    Environment env;
    Text text;

    public updateThread(Environment env, Text text) {
        this.env = env;
        this.text = text;
    }

    public void run() {
        int updatesPerSecond = 2;
        int nbUpdates = 0;
        int targetTime = 1000 / updatesPerSecond;
        long currentTime;
        long lastTime = System.nanoTime();
        long elapsedTime;
        long sleepTime;

        while (nbUpdates < 10) {
            currentTime = System.nanoTime();

            elapsedTime = currentTime - lastTime;
            lastTime = currentTime;

            this.env.update();
            text.setText(this.env.show());

            nbUpdates++;
            sleepTime = targetTime - (elapsedTime / 1000000000);

            if (sleepTime < 0) {
                sleepTime = 1;
            }

            try {
                Thread.sleep(sleepTime);
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
}

What I end up with is after pressing the button, the thread runs and updates the environment correctly, but the scene only changes once, after the thread is done running, and isn't updated when the thread is running. Any idea on how to obtain the result I'm after?

Upvotes: 0

Views: 53

Answers (1)

fabian
fabian

Reputation: 82461

You call Thread.run which runs the Thread's run method on the current thread. You need to use Thread.start instead to create a new thread.

Furthermore updates from a different thread should be done using Platform.runLater:

...
this.env.update();
final String newText = this.env.show();
Platform.runLater(() -> text.setText(newText))
...

Also note that a nanosecond is 10^-9 seconds = 10^-6 milliseconds. You should divide by 1_000_000 instead of 1_000_000_000 and probably do the timing after the environment/UI update since this could take some time too.

Upvotes: 1

Related Questions