我正在尝试创建一个系统,其中使用时间线记录一分钟的持续时间。在这种情况下,我希望时间轴每秒增加一次,并让进度条在调用操作和重置时间轴之前的1分钟内记录下来。
final Timeline timeline = new Timeline();
timeline.setCycleCount(Animation.INDEFINITE);
timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(1)));
progress.progressProperty().bind(timeline.getTotalDuration()???);
timeline.play();
Run Code Online (Sandbox Code Playgroud)
我已将周期数设置为不确定,以便时间轴周期永远不会停止。我还尝试了将Progressbar属性绑定到时间轴,但是它需要Observablevalue来实现,timeline#getTotalDuration但没有提供。
我试过在单独的线程上运行而没有绑定的程序:
new Thread(new Task<Void>() {
@Override
protected Void call() throws Exception {
while(true){
System.out.printf("s:\t%f\n",timeline.getTotalDuration().toSeconds());
Thread.sleep(1000);
}
}
}).start();
Run Code Online (Sandbox Code Playgroud)
但是,运行此命令不会增加每秒的计时器,而只会一次完成所有周期。由于我设置的cycleCount为INDEFINITE,因此结果#totalDuration为infinite。
我如何才能使时间轴每秒工作,如何将持续时间绑定到进度栏,直到达到100%,以便可以调用我的特殊操作?
如果只希望进度条在一分钟的过程中从零开始重复增加到满,并在每分钟结束时执行代码,那么您需要做的是:
ProgressBar progress = new ProgressBar();
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(progress.progressProperty(), 0)),
new KeyFrame(Duration.minutes(1), e-> {
// do anything you need here on completion...
System.out.println("Minute over");
}, new KeyValue(progress.progressProperty(), 1))
);
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
Run Code Online (Sandbox Code Playgroud)
这将为进度条创建一个“模拟”效果,即它不会每秒增加一次,而是在整个分钟内平稳增加。
如果您确实想每秒增加一次,请使用IntegerProperty来代表秒数,然后将进度条的progress属性绑定到该秒数:
ProgressBar progress = new ProgressBar();
IntegerProperty seconds = new SimpleIntegerProperty();
progress.progressProperty().bind(seconds.divide(60.0));
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(seconds, 0)),
new KeyFrame(Duration.minutes(1), e-> {
// do anything you need here on completion...
System.out.println("Minute over");
}, new KeyValue(seconds, 60))
);
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
Run Code Online (Sandbox Code Playgroud)
这里的要点是,IntegerProperty将会在0到60之间进行插值,但只会接受整数值(即,它将被插值的值截断为int)。
这是带有第二个版本的SSCCE:
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Duration;
public class OneMinuteTimer extends Application {
@Override
public void start(Stage primaryStage) {
ProgressBar progress = new ProgressBar();
progress.setMinWidth(200);
progress.setMaxWidth(Double.MAX_VALUE);
IntegerProperty seconds = new SimpleIntegerProperty();
progress.progressProperty().bind(seconds.divide(60.0));
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(seconds, 0)),
new KeyFrame(Duration.minutes(1), e-> {
// do anything you need here on completion...
System.out.println("Minute over");
}, new KeyValue(seconds, 60))
);
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
StackPane root = new StackPane(progress);
root.setPadding(new Insets(20));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Run Code Online (Sandbox Code Playgroud)