JavaFX标签不会持续更新

问题描述:

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

我知道这是某种线程问题。有没有办法使用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(); 
     } 
    } 
    } 
} 

Java8和JavaFx有新的类,使线程更容易。您可以使用AnimationTimer或时间轴。这个例子使用时间轴。

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

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 

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

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