我正在尝试更新Label对象,它是场景中Pane的子级。 标签应该显示从设置的时间开始倒数,我使用了bind函数,StringProperty正在更新,但是节点本身未更新。
这是一个样本。可能看起来很长,但您可以直接将其复制并粘贴到IDE中,这将显示问题。
import javafx.application.*;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.beans.property.*;
import java.util.Timer;
import java.util.TimerTask;
public class LabelUpdateExample extends Application{
private StringProperty timeRemainingText = new SimpleStringProperty();
public static void main(String[] args){
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Stage stage = new Stage();
Pane canvas = new Pane();
TimerField timerField = new TimerField(1);
timeRemainingText = timerField.getTimeText();
Label timeLabel = new Label("Start");
timeLabel.textProperty().bind(timeRemainingText);
// Adds the progress bar to the canvas, setting pref sizes
canvas.setPrefSize(800, 600);
canvas.getChildren().add(timeLabel);
Scene scene = new Scene(canvas, 800, 600);
stage.setScene(scene);
stage.show();
}
/**
* Updates the text to show the new remaining time
*
* @param timeText The text containing the new remaining time
*/
public void setTimeText( StringProperty timeText ) {
this.timeRemainingText = timeText;
System.out.println("timeText: " + timeText.getValue()); // Debugging line
}
/**
* A thingy that manipulates the timer and updates it in the toDoList
*/
class TimerField extends Thread {
private String timeText;
// Variables related to time
private int remTimeInSec;
private int remMin;
private int remSec;
private Timer timer;
/**
* Default constructor of a TimerField object
*
* @throws InterruptedException
*/
public TimerField(int timeInMinutes) throws InterruptedException {
// Sets up the variables related to time
this.remMin = timeInMinutes;
this.remSec = 0;
this.remTimeInSec = timeInMinutes * 60;
// Starts the timer that executes the time update task
timer = new Timer();
timer.scheduleAtFixedRate(new TimeUpdateTask(), 0, 1000);
}
class TimeUpdateTask extends TimerTask{
/**
* Updates the time remaining, or stop everything when time is up
*/
@Override
public void run(){
// TLDR: change the variables to represent one less second
if(remSec > 0){ remSec--; }
else{
remMin--;
remSec = 59;
}
remTimeInSec--;
getTimeText();
// Check for time up
if( remTimeInSec <= 0 ){timer.cancel();}
}
}
/**
* Gives a StringProperty object describing time left
*/
public StringProperty getTimeText( ){
// Creates a new string indicating the remaining time
this.timeText = "Time remaining: " + this.remMin +
"mins " + this.remSec + "secs";
StringProperty timeText = new SimpleStringProperty(this.timeText);
// Update it on the TimedToDoList
setTimeText(timeText);
return timeText;
}
public boolean timeUp(){
return this.remTimeInSec <= 0;
}
}
// end of class TimerField
}
在程序运行时,调试行确实显示StringProperty对象正在更新,这使我感到困惑,因为我认为如果绑定Label的textProperty,则场景中的Label将随着StringProperty更新而更新。任何见识都会有所帮助,谢谢!
答案 0 :(得分:3)
问题是您正在重置对timeRemainingText的引用-因此不再绑定。您需要更改其中的值,而不是对象本身。由于您使用的是计时器,因此需要将线程改回FX线程-有更好的方法来执行此操作,但这不在此问题的范围内。
按如下所述更改一种方法,您将看到这项工作
public void setTimeText( StringProperty timeText ) {
Platform.runLater(() ->
this.timeRemainingText.set(timeText.getValue()));
System.out.println("timeText: " + timeText.getValue()); // Debugging line
}