flirmino
flirmino

Reputation: 11

Update label consecutively using scanner, inJavaFx

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

Answers (2)

James_D
James_D

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

Cypher
Cypher

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

Related Questions