【问题标题】:How do I reset a Timer in Java?如何在 Java 中重置计时器?
【发布时间】:2018-11-09 09:46:50
【问题描述】:

所以我正在尝试使用 Eclipse Oxygen.2 在 Java 中编写一个名为 Lights Out Cube 的手持电子游戏,我决定包含一个计时器,以便玩家知道他需要多少时间才能完成游戏。当玩家点击一个名为“开始/重置”的按钮(点击一次后我将其文本更改为“重置”),这是我激活计时器的地方,游戏开始。每次点击后,我都会检查玩家是否完成了游戏,如果完成了,我会停止计时器。如果他想再玩一次,我希望计时器重新开始。请帮帮我:

//here i have a function called checkIfWinning() which does the checking; if there is a winner, the following code is executed to stop the timer
            timer.cancel();
            timer.purge();
//timer is a publicly declared java.util.Timer
//this is a code snippet for btnStart with "time" recording the time in seconds 
time=0;
timer.schedule(new TimerTask()
            {
                @Override
                    public void run() 
                    {
                            time++;
                            int hours = (int) time / 3600;
                            int remainder = (int) time - hours * 3600;
                            int mins = remainder / 60;
                            remainder = remainder - mins * 60;
                            int secs = remainder;
                            timeTaken.setText(String.format("%02d:%02d:%02d",hours,mins,secs));
                    }

            }, 1000,1000);

无论如何,这可以做到吗?还是我必须完全移除计时器?

【问题讨论】:

  • 您可以取消当前的TimerTask,然后提交一个新的。为了能够取消它,您需要在某处保留对任务的引用。另请参阅使用 ScheduledExecutorService 的替代方法,它类似于 Timer,但更灵活。
  • 也许我遗漏了一些非常明显的东西,但你为什么需要这个定时器呢?你不能只记录用户开始的时间和他们结束的时间,然后从另一个中减去一个吗?

标签: java eclipse timer reset


【解决方案1】:

您无法重置 TimerTask 对象何时被激活,但在您的特定情况下,您可以重置游戏时间计数,而无需移除并重新创建计时器。

由于您的计时器每秒触发一次,因此您只需在用户单击重置按钮时重置您正在使用的time 变量。

我正在根据 Hulks 和您的 cmets 编辑此答案:

  1. Hulk 是对的,你应该使用AtomicInteger 来计算你的时间。如果您保持计时器运行,则有时可能会出现值不会重置的错误。

  2. 您可以设置一个AtomicBoolean 标志,让 TimerTask 知道玩家是否正在玩游戏。

这是一个代码示例:

AtomicInteger time = new AtomicInteger();
//whenever you want to reset it:
time.set(0);

AtomicBoolean isPlaying = new AtomicBoolean();

//when user clicks "start":
isPlaying.set(true);
//when user wins or clicks "reset"
isPlaying.set(false);

//your timer task will look something like this:
public void run() {
    if (isPlaying.get()) {
        int currentTime = time.incrementAndGet();
        int hours = (int) currentTime / 3600;
        int remainder = (int) currentTime - hours * 3600;
        int mins = remainder / 60;
        remainder = remainder - mins * 60;
        int secs = remainder;
        timeTaken.setText(String.format("%02d:%02d:%02d",hours,mins,secs));
    }
}

【讨论】:

  • 请注意,time 变量是从另一个线程(计时器)访问的,因此从外部设置它需要某种同步。最简单的可能是将其变成AtomicInteger
  • 是的,我想过,但我怎样才能冻结屏幕上的时间呢?附言我确实每次都将计数重置为 0。
  • 我试过了,它有效。但问题是每次定时器运行得更快,即每秒更新 2 秒到定时器,然后是 3 和 4 等等。
  • 听起来你在某处仍有一行代码可以在每次玩家开始游戏时创建新的计时器。如果您不删除或取消计时器,则绝对不能创建新计时器。
  • 我重新检查了我的代码,计时器与公共变量一起公开声明,它只是 btnStart 代码中的任务。
【解决方案2】:

这可能很清楚。

  1. 您无法在 Java 中重置或暂停 Timer,但该功能可以通过基于 boolean 检查不运行 Timer 来实现。

  2. 正如之前 Hulk 和 Lev.M 所说,AtomicInteger 可用于需要线程安全。

  3. run() 中的整个逻辑可以使用TimeUnit 将秒转换为指定格式来简化,

    time+=1000;
    System.out.println(String.format("%02d:%02d:%02d", TimeUnit.SECONDS.toHours(time), TimeUnit.SECONDS.toMinutes(time), time%60));
    

import java.util.Timer;
import java.util.TimerTask;

public class Game
{
    private static int time = 0;
    private static Timer t = new Timer();
    private static Game g;
    private static boolean ispaused = false;

    public static void main(String[] args)
    {
        t.schedule(new TimerTask() {
            public void run()
            {
                if(ispaused)
                {
                    return;
                }
                time++;
                System.out.println(String.format("%02d:%02d:%02d", TimeUnit.SECONDS.toHours(time), TimeUnit.SECONDS.toMinutes(time), time%60));
            }
        }, 1000, 1000);

        g = new Game();

        try
        {
            System.out.println("Starting first game");

            g.startGame(); Thread.sleep(5000); g.endGame();

            System.out.println("Starting second game.");

            g.startGame(); Thread.sleep(5000); g.endGame();
        }
        catch(Exception e)
        {}
    }

    private void startGame()
    {
        time = 0;
        ispaused = false;
        System.out.println("Game Started");
    }

    private void endGame()
    {
        time = 0;
        ispaused = true;
        System.out.println("Game ended");
    }
};

【讨论】:

    猜你喜欢
    • 2015-11-13
    • 2010-10-14
    • 2010-11-05
    • 2020-11-14
    • 2013-11-26
    • 2013-11-06
    • 2021-03-11
    • 2011-12-28
    • 1970-01-01
    相关资源
    最近更新 更多