我的计时器在Java中无法正确计数

时间:2017-06-14 20:21:26

标签: java timer timertask

因此,我正在使用Java制作游戏,并且想要在用户按下"播放"之后使用计时器从游戏屏幕上的3倒计时。在菜单屏幕上。

这是我的代码:

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);
}

我在游戏的draw方法中使用倒计时:

public void draw(Graphics g) {

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

    //count
    countdown(g);
}

我正在使用控制台打印数字,但我会更改此设置以便稍后使用 drawString()在屏幕上绘制倒计时。

按下"播放"在我的菜单屏幕上,我的游戏屏幕上有一秒暂停,然后所有数字都打印到控制台。问题是打印数字之间没有一秒钟的延迟,它们只是同时打印所有。有什么帮助吗?

3 个答案:

答案 0 :(得分:1)

如果反复调用draw,则会创建多个计时器,因此您将从每个计时器中获取打印输出,这也将减少秒计数。

您可以尝试创建单个计时器,而不是在每个倒计时功能中创建,只需让倒计时功能设置秒值。

答案 1 :(得分:1)

您的程序似乎是Swing或AWT GUI程序,如果是这样,您使用了错误类型的计时器,这里只有java.util.Timerjava.util.TimerTask,两者都不是摆动螺纹安全。这可能导致您的GUI冻结,并且数字不会显示,就像您正在查看一样。而是使用专为这些GUI构建的计时器,Swing Timer (click on this link for the tutorial)。您还从绘图代码中调用计时器,这与您应该执行的操作完全相反。相反,Timer应该更改计数变量的状态,然后调用repaint()。然后,绘图代码获取计数变量的值并将其显示在GUI中。

例如,您的Swing Timer可以使用ActionLerner,其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());
    }
}

答案 2 :(得分:0)

您在创建和/或取消计时器时必须重置 Timer timer = new Timer(); seconds = 3; //Reset here .......... .......... if(seconds == -1) { timer.cancel(); seconds = 3; // Reset here } 变量

[
    {
        "expand": "description,lead,url,projectKeys",
        "self": "http://",
        "id": "10802",
        "key": "TE",
        "name": "TEST TEST",
        "avatarUrls": {
            "48x48": "http://",
            "24x24": "http://",
            "16x16": "http://",
            "32x32": "http://"
        },
        "projectCategory": {
            "self": "http://",
            "id": "10200",
            "name": "TTTTTT",
            "description": "TTTTTTTT"
        },
        "projectTypeKey": "software"
    },
    {
        "expand": "description,lead,url,projectKeys",
        "self": "http://",
        "id": "10801",
        "key": "TT",
        "name": "TREINAMENTO TESTE",
        "avatarUrls": {
            "48x48": "http://",
            "24x24": "http://",
            "16x16": "http://",
            "32x32": "http://"
        },
        "projectTypeKey": "business"
    }
]