Ethyl Casin Ethyl Casin - 2 months ago 52
Java Question

Append text to JavaFX TextArea during updateProgress

I have this simple code below which updates the

TextArea
during
updateProgress
:

textArea = new TextArea();
textArea.setEditable(false);
textArea.setFocusTraversable(false);

StackPane root = new StackPane();
root.setPadding(new Insets(10));
root.getChildren().add(textArea);

Scene scene = new Scene(root, 600, 350);

primaryStage.setTitle("JavaFX Concurrency");
primaryStage.setScene(scene);
primaryStage.show();

task = new Task<Integer>(){
@Override
protected Integer call() throws Exception {
int i;
for(i = 1; i <= 100; i++){
updateProgress(i, 100);
}
return i;
}
};
task.stateProperty().addListener(new ChangeListener<State>(){
@Override
public void changed(ObservableValue<? extends State> observable, State oldValue, State state) {
System.out.println(state);
}
});
task.progressProperty().addListener(new ChangeListener<Number>(){
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number val) {
Platform.runLater(new Runnable(){
@Override
public void run() {
textArea.appendText("Value : " + val.intValue() + "\n");
}
});
}
});
new Thread(task).start();


But unfortunately the result was wrong. Here's the output:

enter image description here

I was expecting that the output should be Value : 1 to Value : 100..

I was just trying to test the concurrency package in JavaFX. Can someone tell me what's going on?

Answer Source

If you insert a simple:

Thread.sleep(10);

after you call updateProgress(i, 100);, everything will be better. This comes from the documentation of updateProgress:

Calls to updateProgress are coalesced and run later on the FX application thread, and calls to updateProgress, even from the FX Application thread, may not necessarily result in immediate updates to these properties, and intermediate workDone values may be coalesced to save on event notifications. max becomes the new value for totalWork.

After this you can experience that more text-lines are appended to your text box, but:

This does not ensure that all of your updates will be done on your textbox!

If you want to ensure this, call the GUI update directly in the call() of task wrapped in the Platform.runlater(...) block.