因此,这是我目前用于倒计时工作的方法。
/**
* Starts the count-down
* Triggers the handleFinish method
* Sets the user under time pressure, which actually is a good way to provocate the user to start over again, to beat the score already achieved
*/
public void startCountDown() {
countDownText.setVisible(true);
timer.schedule(new TimerTask() {
@Override
public void run() {
Platform.runLater(new Runnable() {
public void run() {
if(hasFinished)
return;
countDown--;
countDownText.setText("Time left:" + countDown);
if (countDown < 1)
handleFinish();
}
});
}
}, 1000, 1000); //Every 1 second
}
handleFinish方法
/**
* Action after the timer runs out
* Disables the button, and sets a new highscore if the achieved score is greater than the current highscore
* @param highScore
*/
public void handleFinish() {
mainButton.setDisable(true);
mainButton.setText("Disabled.");
if(score > highScore) {
highScore = score;
saveData();
notificationText.setText("Notification: New highscore! " + highScore);
notificationText.setVisible(true);
resetStats();
countDownText.setVisible(false);
System.out.println("New Highscore");
return;
} else {
appearDialogue("You didn't beat your highscore! :( Try it again!");
resetStats();
}
hasFinished = true;
}
resetStats方法
/**
* Resets the stats
* Changes the text of the button, sets the boolean and int @param hasStarted/ @param score to default (false) (0)
* Sets the position of the button to the default one
*/
public void resetStats() {
timer.purge();
mainButton.setText("Click to start..");
hasStarted = false;
score = 0;
mainButton.setLayoutX(201);
mainButton.setLayoutY(157);
countDown = 20;
scoreText.setVisible(false);
mainButton.setDisable(false);
System.out.println("STATS RESET");
}
calculatePosition也是一个计时器(TimerTask)
现在我的问题是,他们开始&#34;多线程&#34;,就像越来越多的对象实例一样。 (相反,一个计时器倒计时,有2个实例在运行,所以 - 每1秒2秒)。计算位置问题也是如此。
instance.purge();
清除只是重置计时器 如果我正在使用
instance.cancel();
它向我抛出了这个错误:
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$MethodHandler.invoke(Unknown Source)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(Unknown Source)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
at javafx.event.Event.fireEvent(Unknown Source)
at javafx.scene.Scene$ClickGenerator.postProcess(Unknown Source)
at javafx.scene.Scene$ClickGenerator.access$7900(Unknown Source)
at javafx.scene.Scene$MouseHandler.process(Unknown Source)
at javafx.scene.Scene$MouseHandler.access$1500(Unknown Source)
at javafx.scene.Scene.impl_processMouseEvent(Unknown Source)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Unknown Source)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(Unknown Source)
at com.sun.glass.ui.View.handleMouseEvent(Unknown Source)
at com.sun.glass.ui.View.notifyMouse(Unknown Source)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$141(Unknown Source)
at com.sun.glass.ui.win.WinApplication$$Lambda$37/1109371569.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.reflect.misc.Trampoline.invoke(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.reflect.misc.MethodUtil.invoke(Unknown Source)
... 31 more
Caused by: java.lang.IllegalStateException: Timer already cancelled.
at java.util.Timer.sched(Unknown Source)
at java.util.Timer.schedule(Unknown Source)
at MainController.startCountDown(MainController.java:233)
at MainController.start(MainController.java:91)
... 40 more
当发生此错误时,calculatePosition任务确实正常工作(不会自行增加)
感谢帮助! :)
亲切的问候, 亚辛答案 0 :(得分:1)
您可以使用TimerTask
而不是Timeline
。阅读更多here。
这是我游戏的简短版本:
private static final Integer TOTALTIME = 20;
private final IntegerProperty count = new SimpleIntegerProperty(TOTALTIME);
private final Label timerLabel = new Label();
private final Button btn = new Button("Start countdown");
@Override
public void start(Stage primaryStage) {
timerLabel.textProperty().bind(count.asString());
timerLabel.setVisible(false);
final Timeline timeline = new Timeline();
timeline.setCycleCount(TOTALTIME);
KeyFrame keyFrame = new KeyFrame(Duration.seconds(1), e->count.set(count.get()-1));
timeline.getKeyFrames().add(keyFrame);
timeline.setOnFinished(e->handleFinish());
btn.setOnAction(e->{
btn.setDisable(true);
timerLabel.setVisible(true);
timeline.playFromStart();
});
VBox root = new VBox(20,timerLabel,btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
private void handleFinish() {
timerLabel.setVisible(false);
btn.setDisable(false);
resetStats();
}
private void resetStats() {
count.set(TOTALTIME);
}
请注意,您不需要Platform.runLater()
,因为所有内容都在JavaFX应用程序线程上执行。