如何在 JavaFX 中重新启动计时器?
How to restart a timer in JavaFX?
我目前正在开发一个程序,用户可以在其中为不同的练习创建他们的时间间隔。一旦按下开始,第一个练习开始倒计时。完成后,会播放声音,第二个开始倒计时,依此类推,直到所有练习都完成并移除。我使用了一个计时器,它每 1 秒后将练习时间减去 1。问题是,我似乎无法在 java 中找到重新启动计时器的方法。完成所有练习后,我可以停止计时器,但当我想创建新练习并再次完成该过程时,我似乎找不到重新启动它的方法。我也找不到在特定过程中暂停并再次播放计时器的方法。我是 JavaFX 的新手,所以如果您能指导我如何更改代码以实现我正在寻找的目标,我将不胜感激。
Timer timer = new Timer();
startButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
//Timer task=new TimerTask();
timer.schedule(new TimerTask() {
@Override
public void run() {
running=true;
if (running==true)
{
if (workoutsList.size() == 0) {
return;
}
if (workoutsList.size() == 1 && workoutsList.get(0).time == 1) {
text.setText("over!");
mediaPlayer1.play();
workoutsList.clear();
workouts.getItems().clear();
timer.cancel();
return;
}
workoutsList.get(0).time -= 1;
if (workoutsList.get(0).time == 0) {
workoutsList.remove(0);
mediaPlayer.play();
return;
}
workouts.getItems().clear();
workouts.refresh();
for (int i = 0; i < workoutsList.size(); i++) {
workouts.getItems().add(workoutsList.get(i));
}
}
}
}, 0, 1000);
}
});
stopButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
timer.cancel();
running=false;
}
});
因为 Timer
除了跟踪时间之外什么都不做,所以最好使用 javafx.animation
API。这给了你一些优势:
- 一切都发生在 JavaFX 应用程序线程,这意味着没有并发问题。
- 您可以使用
Animation
的 currentTime
和 cycleDuration
属性来跟踪倒计时中剩余的时间。
- 您可以使用
Animation
的play()
、pause()
和stop()
方法来控制定时器。
- 您可以使用
Animation
的 onFinished
属性 在计时器结束时播放您的声音。
这是一个使用 PauseTransition
的示例,但您也可以使用例如Timeline
.
import javafx.animation.Animation;
import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringBinding;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
// javafx.util.Duration
PauseTransition timer = new PauseTransition(Duration.minutes(5));
// timer.setOnFinished(e -> /* play sound */);
Button startBtn = new Button("Start");
startBtn.setOnAction(e -> timer.play());
Button pauseBtn = new Button("Pause");
pauseBtn.setOnAction(e -> timer.pause());
Button resetBtn = new Button("Reset");
resetBtn.setOnAction(e -> timer.stop());
Label label = new Label();
label.setFont(Font.font("Monospaced", 20));
label.textProperty().bind(timeLeftAsString(timer));
HBox hbox = new HBox(10, startBtn, pauseBtn, resetBtn);
hbox.setAlignment(Pos.CENTER);
VBox root = new VBox(25, label, hbox);
root.setPadding(new Insets(25));
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private StringBinding timeLeftAsString(Animation animation) {
return Bindings.createStringBinding(
() -> {
double currentTime = animation.getCurrentTime().toMillis();
double totalTime = animation.getCycleDuration().toMillis();
long remainingTime = Math.round(totalTime - currentTime);
// java.time.Duration
java.time.Duration dur = java.time.Duration.ofMillis(remainingTime);
return String.format(
"%02d:%02d:%03d", dur.toMinutes(), dur.toSecondsPart(), dur.toMillisPart());
},
animation.currentTimeProperty(),
animation.cycleDurationProperty());
}
}
旁注:您提到计时器完成时会播放声音,我可以看到对 mediaPlayer.play()
的调用。考虑到程序的性质,我假设正在播放的声音相对较短。如果是这种情况,您应该考虑使用 AudioClip
而不是 MediaPlayer
.
我目前正在开发一个程序,用户可以在其中为不同的练习创建他们的时间间隔。一旦按下开始,第一个练习开始倒计时。完成后,会播放声音,第二个开始倒计时,依此类推,直到所有练习都完成并移除。我使用了一个计时器,它每 1 秒后将练习时间减去 1。问题是,我似乎无法在 java 中找到重新启动计时器的方法。完成所有练习后,我可以停止计时器,但当我想创建新练习并再次完成该过程时,我似乎找不到重新启动它的方法。我也找不到在特定过程中暂停并再次播放计时器的方法。我是 JavaFX 的新手,所以如果您能指导我如何更改代码以实现我正在寻找的目标,我将不胜感激。
Timer timer = new Timer();
startButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
//Timer task=new TimerTask();
timer.schedule(new TimerTask() {
@Override
public void run() {
running=true;
if (running==true)
{
if (workoutsList.size() == 0) {
return;
}
if (workoutsList.size() == 1 && workoutsList.get(0).time == 1) {
text.setText("over!");
mediaPlayer1.play();
workoutsList.clear();
workouts.getItems().clear();
timer.cancel();
return;
}
workoutsList.get(0).time -= 1;
if (workoutsList.get(0).time == 0) {
workoutsList.remove(0);
mediaPlayer.play();
return;
}
workouts.getItems().clear();
workouts.refresh();
for (int i = 0; i < workoutsList.size(); i++) {
workouts.getItems().add(workoutsList.get(i));
}
}
}
}, 0, 1000);
}
});
stopButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
timer.cancel();
running=false;
}
});
因为 Timer
除了跟踪时间之外什么都不做,所以最好使用 javafx.animation
API。这给了你一些优势:
- 一切都发生在 JavaFX 应用程序线程,这意味着没有并发问题。
- 您可以使用
Animation
的currentTime
和cycleDuration
属性来跟踪倒计时中剩余的时间。 - 您可以使用
Animation
的play()
、pause()
和stop()
方法来控制定时器。 - 您可以使用
Animation
的onFinished
属性 在计时器结束时播放您的声音。
这是一个使用 PauseTransition
的示例,但您也可以使用例如Timeline
.
import javafx.animation.Animation;
import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringBinding;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
// javafx.util.Duration
PauseTransition timer = new PauseTransition(Duration.minutes(5));
// timer.setOnFinished(e -> /* play sound */);
Button startBtn = new Button("Start");
startBtn.setOnAction(e -> timer.play());
Button pauseBtn = new Button("Pause");
pauseBtn.setOnAction(e -> timer.pause());
Button resetBtn = new Button("Reset");
resetBtn.setOnAction(e -> timer.stop());
Label label = new Label();
label.setFont(Font.font("Monospaced", 20));
label.textProperty().bind(timeLeftAsString(timer));
HBox hbox = new HBox(10, startBtn, pauseBtn, resetBtn);
hbox.setAlignment(Pos.CENTER);
VBox root = new VBox(25, label, hbox);
root.setPadding(new Insets(25));
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private StringBinding timeLeftAsString(Animation animation) {
return Bindings.createStringBinding(
() -> {
double currentTime = animation.getCurrentTime().toMillis();
double totalTime = animation.getCycleDuration().toMillis();
long remainingTime = Math.round(totalTime - currentTime);
// java.time.Duration
java.time.Duration dur = java.time.Duration.ofMillis(remainingTime);
return String.format(
"%02d:%02d:%03d", dur.toMinutes(), dur.toSecondsPart(), dur.toMillisPart());
},
animation.currentTimeProperty(),
animation.cycleDurationProperty());
}
}
旁注:您提到计时器完成时会播放声音,我可以看到对 mediaPlayer.play()
的调用。考虑到程序的性质,我假设正在播放的声音相对较短。如果是这种情况,您应该考虑使用 AudioClip
而不是 MediaPlayer
.