Reputation: 11
I'm currently trying to learn JavaFx, and I'm now stuck on a problem. By using a scanner I want to update my label on stage consecutively.
I have tried to use platform.runLater, but this only shows one update. It doesnt update the label every time I write something new in my console.
This is what I have been using:
Platform.runLater(new Runnable() {
@Override
public void run() {
label.setText(sc.nextLine());
}
});
Upvotes: 1
Views: 124
Reputation: 209330
The nextLine()
method in Scanner
is a blocking call: you should never block the FX Application Thread. You need to create a background thread to read from the scanner, and then update the label on the FX Application Thread:
import java.util.Scanner;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class UpdateLabelFromScanner extends Application {
@Override
public void start(Stage primaryStage) {
Label label = new Label();
Thread scannerReadThread = new Thread(() -> {
try (Scanner scanner = new Scanner(System.in)) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine() ;
Platform.runLater(() -> label.setText(line));
}
} catch (Exception exc) {
exc.printStackTrace();
}
});
scannerReadThread.setDaemon(true);
scannerReadThread.start();
StackPane root = new StackPane(label);
primaryStage.setScene(new Scene(root, 180, 120));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 2
Reputation: 2687
There are a few ways you can do this. One way to is to read the text into an observable property, and when that property changes, you update your label. One of the objects you can use to do this is called SimpleStringProperty.
Declare it like this:
private StringProperty someText = new SimpleStringProperty();
In a constructor or some initialization function, add a new ChangeListener to the property:
someText.addListener((observable, oldValue, newValue) -> {
Platform.runLater(() -> {
label.setText(newValue);
});
});
When you read input from your scanner, change the value of your observable and the listener you added will be invoked, thus changing the text of your label:
someText.set(sc.nextLine());
Upvotes: 0