Kkk.
Kkk.

Reputation: 1

JavaFX update text from Task

I want to change text I create a task and increment i, but I want to set a new text on this same place when i is changed, but old text doesn't disappear. It's my code. On swing I will be use repaint()

Task task = new Task<Void>() {
    @Override
    public Void call() throws Exception {
        int i = 0;
        while (true) {
          final int finalI = i;
          Platform.runLater(new Runnable() {
            @Override
            public void run() {

                String a = "aaa";
                if(finalI>4){
                    a = "sadsa";
                }
                if(finalI>10){
                    a = "sadsadsadsadsad";
                }
                gc.fillText(a, 150, 250+10);
            }
          });
          i++;
          Thread.sleep(1000);
        }
    }
};
Thread th = new Thread(task);
th.setDaemon(true);
th.start();

Upvotes: 2

Views: 6030

Answers (1)

DVarga
DVarga

Reputation: 21799

As I mentioned in my comment, the problem is that Canvas really acts like a drawing board. You have drawn some text on it then you have drawn another text without erasing the previous text.

In your case, when you want to store a reference to the text to be able to update it, it is more reasonable to use a Pane and put a Text instance on it.

I have created an example for you:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.text.Text;

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root, 400, 400);

            Pane pane = new Pane();
            Text text = new Text("");
            pane.getChildren().add(text);
            Task<Void> task = new Task<Void>() {
                String a = "Initial text";

                @Override
                public Void call() throws Exception {
                    int i = 0;

                    while (true) {

                        if (i > 4)
                            a = "I is bigger than 4";

                        if (i > 10)
                            a = "I is bigger than 10";

                        Platform.runLater(() -> {
                            text.setText(a);
                            // If you want to you can also move the text here
                            text.relocate(10, 10);
                        });

                        i++;
                        Thread.sleep(1000);
                    }
                }
            };
            Thread th = new Thread(task);
            th.setDaemon(true);
            th.start();

            root.setCenter(pane);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Note: You can also eliminate the Platform.runlater(...) block by updating the messageProperty of the task inside call() then binding the textProperty of the Text to this property.

Example:

Pane pane = new Pane();
Text text = new Text("");
text.relocate(10, 10);

pane.getChildren().add(text);
Task<Void> task = new Task<Void>() {
    {
        updateMessage("Initial text");
    }

    @Override
    public Void call() throws Exception {
        int i = 0;

        while (true) {
            if (i > 4)
                updateMessage("I is bigger than 4");

            if (i > 10)
                updateMessage("I is bigger than 10");

            i++;
            Thread.sleep(1000);
        }
    }
};

text.textProperty().bind(task.messageProperty());

Thread th = new Thread(task);
th.setDaemon(true);
th.start();

Upvotes: 3

Related Questions