JavaFX label will not continuously update

蹲街弑〆低调 提交于 2019-12-12 04:57:18

问题


Unfortunately, I have fallen prey to the continuously updating label problem. While searching for a solution, I found an answer with many upvotes that suggested binding my label to a StringProperty, and then whenever that StringProperty is changed, the label's text would subsequently be changed. However, I cannot for the life of me get it to work.

I know that it's a threading issue of some sort. Is there a way to solve the problem using a DataBinding solution, etc, or is threading the only option? If threading is the only option, could you point me in the right direction? I haven't found a nice solution using threading either...

Any help would be appreciated!

Program Description: The desired function of the program below is to have the label continuously update as it counts from 0-10 in a for loop.

public class First extends Application {
Stage mainStage;
Scene mainScene;

Button mainButton;
Label mainLabel;

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

@Override
public void start(Stage stage) throws Exception {

    mainStage = stage;
    mainButton = new Button("Begin!");
    mainLabel = new Label("Ready");

    VBox box = new VBox(50);
    box.getChildren().addAll(mainLabel, mainButton);

    mainScene = new Scene(box, 200, 200);
    mainStage.setScene(mainScene);
    mainStage.setTitle("Test Program");
    mainStage.show();

    //Handles Button Press
    mainButton.setOnAction(e -> {
        Second s = new Second();
        mainLabel.textProperty().bind(s.getProperty());
        s.count();
    });
  }
}

Here is the second class:

public class Second {

private StringProperty strP = new SimpleStringProperty(this, "strProperty", "");

//Get Property
public StringProperty getProperty() {
    return strP;
}

//Get String
public String getString() {
    return strP.get();
}

//Changes StringProperty every 0.25s
public void count() {

    for (int i = 0; i <= 10; i++) {

        this.strP.set(Integer.toString(i));

        try {
            Thread.sleep(250);
        } catch (InterruptedException e) {

            e.printStackTrace();
        }
    }
  }
}

回答1:


Java8 and JavaFx have new Classes that make threads easier. You can use AnimationTimer or Timeline. This example uses Timeline.

import javafx.animation.*;
import javafx.application.*;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;
import javafx.util.*;

/**
 *
 * @author Sedrick
 */
public class First  extends Application {

    Stage mainStage;
    Scene mainScene;

    Button mainButton;
    Label mainLabel;

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

    @Override
    public void start(Stage stage) throws Exception
    {

        mainStage = stage;
        mainButton = new Button("Begin!");
        mainLabel = new Label("Ready");

        VBox box = new VBox(50);
        box.getChildren().addAll(mainLabel, mainButton);

        mainScene = new Scene(box, 200, 200);
        mainStage.setScene(mainScene);
        mainStage.setTitle("Test Program");
        mainStage.show();

        //Handles Button Press
        mainButton.setOnAction(e -> {
            Second s = new Second();
            mainLabel.textProperty().bind(s.getProperty());
            Timeline timeline = new Timeline(
                    new KeyFrame(Duration.seconds(0),
                            new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent actionEvent)
                        {
                            s.setStrP(Integer.toString(Integer.parseInt(s.getStrP()) + 1));//I think you should have used an Integer here.
                        }
                    }
                    ),
                    new KeyFrame(Duration.seconds(1))//Do something every second. In this case we are going to increment setStrP.
            );
            timeline.setCycleCount(10);//Repeat this 10 times
            timeline.play();
        });
    }
}



import javafx.beans.property.*;

public class Second {

    private StringProperty strP = new SimpleStringProperty();

    Second()
    {
        setStrP("0");//set to zero
    }
//Get Property

    public StringProperty getProperty()
    {
        return strP;
    }

//Get String
    public String getStrP()
    {
        return strP.get();
    }

//Changes StringProperty every 0.25s
    public void setStrP(String i)
    {
        this.strP.set(i);
    }
}



回答2:


Personally in JavaFX, I usually create a counter like this (You can take the idea and apply it to your project):

Label timerLabel = new Label();
Timer timer = new Timer();
int count = 0;
timer.schedule(new TimerTask() { // timer task to update the seconds
    @Override
    public void run() {
        // use Platform.runLater(Runnable runnable) If you need to update a GUI component from a non-GUI thread.
        Platform.runLater(new Runnable() { 
            public void run() {
                timerLabel.setText("Second : " + count);
                count++;
                if (count >= 10){timer.cancel();}
}});}}, 1000, 1000); //Every 1 second



回答3:


you can change a value of label itself by a Timeline or Task class.

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;

public class First extends Application {
    Stage mainStage;
    Scene mainScene;

    Button mainButton;
    Button mainButton2;
    Label mainLabel;

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

    }

    @Override
    public void start(Stage stage) throws Exception {

        mainStage = stage;
        mainButton = new Button("Begin!");
        mainButton2 = new Button("Begin2!");
        mainLabel = new Label("Ready");

        VBox box = new VBox(50);
        box.getChildren().addAll(mainLabel, mainButton, mainButton2);

        mainScene = new Scene(box, 200, 200);
        mainStage.setScene(mainScene);
        mainStage.setTitle("Test Program");
        mainStage.show();


        mainButton.setOnAction(e -> {
            final Second s = new Second();

            mainLabel.textProperty().bind(s.getProperty());

            Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(0), new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent actionEvent) {
                    s.count();
                }
            }), new KeyFrame(Duration.seconds(Second.DURATION)));

            timeline.setCycleCount(11);
            timeline.play();

        });

        mainButton2.setOnAction(event -> {
            final Second s = new Second();
            s.count2(mainLabel);

        });

        //
    }
}

class Second {

    private StringProperty strP = new SimpleStringProperty(this, "strProperty", "");
    private int myCount;
    public static float DURATION = 0.25F;
    public static long DURATION_SEC = (long)DURATION * 1000;

    Second()
    {
        myCount = 0;
    }

    public void count2(final Label mainLabel) {
        Task<Void> task = new Task<Void>() {
            @Override 
            public Void call() throws Exception {
                for (int i=1; i<=10; i++) {
                    updateMessage("Count: "+i);
                    Thread.sleep(DURATION_SEC);
                }
                return null ;
            }
        };

        task.messageProperty().addListener((obs, oldMessage, newMessage) -> mainLabel.setText(newMessage));
        new Thread(task).start();
    }

    // Get Property
    public StringProperty getProperty() {
        return strP;
    }

    // Get String
    public String getString() {
        return strP.get();
    }

    public void count()
    {
        this.strP.set("Count: "+myCount++);
    }

}



来源:https://stackoverflow.com/questions/44060204/javafx-label-will-not-continuously-update

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!