JavaFX标签不会持续更新

时间:2017-05-19 01:50:36

标签: java multithreading javafx label

不幸的是,我已经成为持续更新标签问题的牺牲品。在搜索解决方案时,我找到了许多upvotes的答案,建议将我的标签绑定到StringProperty,然后每当更改StringProperty时,标签的文本随后都会被更改。但是,我不能为我的生活得到它的工作。

我知道这是某种线程问题。有没有办法使用DataBinding解决方案等解决问题,或者是线程唯一的选择?如果线程是唯一的选择,你能指出我正确的方向吗?我还没有找到使用线程的好解决方案......

任何帮助将不胜感激!

程序说明:下面程序的所需功能是让标签在for循环中从0-10开始不断更新。

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();
    });
  }
}

这是第二节课:

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();
        }
    }
  }
}

3 个答案:

答案 0 :(得分:1)

就个人而言, JavaFX ,我通常会创建一个这样的计数器(你可以把这个想法运用到你的项目中):

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

答案 1 :(得分:0)

Java8和JavaFx都有新的类,使线程更容易。您可以使用AnimationTimer或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 :(得分:0)

您可以通过时间轴或任务类更改标签本身的值。

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++);
    }

}

enter image description here