计时器和计算有多个实例在运行

时间:2014-11-02 10:14:03

标签: java timer javafx

因此,这是我目前用于倒计时工作的方法。

 /**
     * 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任务确实正常工作(不会自行增加)

感谢帮助! :)

亲切的问候, 亚辛

1 个答案:

答案 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应用程序线程上执行。