2017-06-14 111 views
1

因此,我正在制作一款使用Java的游戏,并希望在用户在菜单屏幕上按下“播放”后,使用计时器从游戏屏幕上的3倒计时。我的计时器在Java中不能正确计数

这里是我的代码:

int seconds = 3; 

private void countdown(Graphics g) { 

    Timer timer = new Timer(); 

    TimerTask task = new TimerTask() { 
     public void run() { 
      if(seconds >= 0) { 
       System.out.println(seconds); 
       seconds--; 
      } 
      if(seconds == -1) { 

       timer.cancel(); 
      } 
     } 
    }; 

    timer.schedule(task, 1000, 1000); 
} 

我用倒计时在我比赛的抽签方法在这里:

public void draw(Graphics g) { 

    //background 
    g.setColor(Color.BLACK); 
    g.fillRect(0, 0, WIDTH, HEIGHT); 

    //count 
    countdown(g); 
} 

我使用控制台打印的数字,但是我会改变这稍后使用drawString()在屏幕上绘制倒数。

在我的菜单屏幕上按下“play”后,我的游戏屏幕上会暂停一秒,然后数字全部打印到控制台。问题是在打印数字之间没有第二个延迟,他们只是同时打印所有数字。任何帮助?

+0

工作正常,我。请发布[mcve]。 – shmosel

+0

您是否使用绘图方法并以秒为单位递减1秒? –

+0

我只是做了'countdown()'方法,它以1秒为间隔计数到0。我不明白'draw()'方法是如何与问题相关的。 – shmosel

回答

1

如果draw被重复调用,那么将会创建多个定时器,这样您将从每个定时器获得打印输出,这也会减少秒数。

您可以尝试创建一个计时器,而不是在每个倒计时函数中创建,并且只需使倒计时功能设置秒数值即可。

+0

我该如何解决这个问题,所以它不会重复调用,但仍然将计时器绘制到屏幕上? –

+0

你的意思是这样吗? 'private int seconds = 3; \t private Timer timer = new Timer(); \t \t私人无效倒计时(图形克){ \t \t \t \t TimerTask的任务=新的TimerTask(){ \t \t \t公共无效的run(){ \t \t \t \t如果(秒> = 0){ \t \t \t \t \t的System.out.println(秒); \t \t \t \t \t秒 - ; \t \t \t \t} \t \t \t \t如果(秒== -1){ \t \t \t \t \t timer.cancel(); \t \t \t \t} \t \t \t} \t \t}; \t \t \t \t timer.schedule(task,1000,1000); \t}' –

+0

我道歉,我不知道如何格式化最后一个。 –

0

,必须重置当您创建和/或取消计时器

seconds变量
 Timer timer = new Timer(); 
     seconds = 3; //Reset here 
     .......... 
     .......... 

     if(seconds == -1) { 
      timer.cancel(); 
      seconds = 3; // Reset here 
     } 
+0

当我这样做时,它只是非常快速地重复从3到0的倒计数,并没有停止。 –

+0

这意味着你有多个任务创建..这是你打算做什么? – Zakir

+0

我最初打算使用_drawString()_在屏幕上进行倒计时显示,而我只是希望计时器从3到0进行计数。我最初只需要一个任务。 –

1

你的计划似乎是一个Swing或AWT GUI程序,如果是这样,你使用了错误的类型的Timer,这里是java.util.Timerjava.util.TimerTask,这两者都不是Swing线程安全的。这可能会导致您的GUI冻结,并且数字不会显示出来,就像您看到的一样。而应使用专门为这些GUI构建的计时器,一个Swing Timer (click on this link for the tutorial)。你也从绘图代码中调用计时器,这与你应该做的事情完全相反。相反,定时器应该改变你的计数变量的状态,然后调用repaint()。绘图代码然后获取计数变量的值并将其显示在GUI中。

例如,你的挥杆定时器可以使用一个ActionListener其actionPerformed方法看起来是这样的:

public void actionPerformed(ActionEvent e) { 
    if (counter != 0) { 
     // if the counter hasn't reached the end 
     counter--; // reduce counter by one 
     repaint(); // tell the GUI to repaint 
    } else { 
     timer.stop(); // otherwise at the end, so stop the timer 
     countDownAction.setEnabled(true); // and re-enable the button 
    } 
} 

一个完整的GUI例子看起来是这样的:

import java.awt.Dimension; 
import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class CountDown extends JPanel { 
    public static final int TIMER_DLEAY = 1000; 
    private static final Font COUNTER_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 400); 
    private static final int TEXT_X = 200; 
    private static final int TEXT_Y = 500; 
    private int counter; 
    private JSpinner spinner = new JSpinner(new SpinnerNumberModel(5, 0, 20, 1)); 
    private CountDownAction countDownAction = new CountDownAction("Count Down"); 
    private JButton countDownButton = new JButton(countDownAction); 
    private Timer timer; 

    public CountDown() { 
     setPreferredSize(new Dimension(800, 600)); 
     add(new JLabel("Starting Value:")); 
     add(spinner); 
     add(countDownButton); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 
       RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 
     g.setFont(COUNTER_FONT); 
     String text = String.format("%02d", counter); 
     g.drawString(text, TEXT_X, TEXT_Y); 
    } 

    private class CountDownAction extends AbstractAction { 
     public CountDownAction(String name) { 
      super(name); 
      int mnemonic = (int) name.charAt(0); 
      putValue(MNEMONIC_KEY, mnemonic); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      // inactivate the button/action 
      countDownAction.setEnabled(false); 
      counter = (int) spinner.getValue(); 
      repaint(); 
      timer = new Timer(TIMER_DLEAY, new TimerListener()); 
      timer.start(); 
     } 
    } 

    private class TimerListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      if (counter != 0) { 
       // if the counter hasn't reached the end 
       counter--; // reduce counter by one 
       repaint(); // tell the GUI to repaint 
      } else { 
       timer.stop(); // otherwise at the end, so stop the timer 
       countDownAction.setEnabled(true); // and re-enable the button 
      } 
     } 
    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("CountDown"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new CountDown()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
}