Java - Swing Timer开始显示比预期更晚的时间

时间:2017-02-21 19:15:52

标签: java swing timer

我正在制作游戏。我希望有一个类似时钟的东西,显示从游戏的乞讨过了多少时间。它工作得很好,但它可能比实际游戏开始晚一两秒。我不知道是什么原因,所以我很感激任何帮助。谢谢!

我创建了一个类似的情况(runnable)。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.TimeUnit;
import javax.swing.Timer;


public class GUI extends javax.swing.JFrame {

    private Timer SimpleTimer;

    public GUI() {
        initComponents();
    }

    private void initComponents() {

        jLabel1 = new javax.swing.JLabel();
        jButton1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jButton1.setText("jButton1");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(154, 154, 154)
                        .addComponent(jLabel1))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(131, 131, 131)
                        .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap(196, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(92, Short.MAX_VALUE)
                .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(48, 48, 48)
                .addComponent(jLabel1)
                .addGap(137, 137, 137))
        );

        pack();
    }                      

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        startGame();
    }                                        

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new GUI().setVisible(true);
            }
        });
    }

    private javax.swing.JButton jButton1;
    private javax.swing.JLabel jLabel1;             

    private void startGame() {
        long startTime = System.currentTimeMillis();
        if(SimpleTimer != null) {
            SimpleTimer.stop();
        }
        SimpleTimer = new Timer(1000, new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                long millis = System.currentTimeMillis() - startTime;
                jLabel1.setText("Time passed: " + String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(millis),
            TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
            TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))));
            }
        });
        SimpleTimer.start();
    }
}

1 个答案:

答案 0 :(得分:4)

你的时间计算了。不应该是这样的:

this.chartTitle = data.Name;
this.doughnutChartLabels[0] = data.Data.Issues[0].Values[0].Value;
this.doughnutChartLabels[1] = data.Data.Issues[1].Values[0].Value;
this.doughnutChartData[0] = data.Data.Issues[0].Values[2].Value;
this.doughnutChartData[1] = data.Data.Issues[1].Values[2].Value;

修改:不,您的转化没问题。我建议您的Timer使用更精细的粒度,然后1秒,如果您显示1秒单位。在这里,我使用100毫秒的粒度。

请注意,您的代码不会为我运行(请尝试复制并运行已发布的代码以查看其功能)。

请查看下面的MCVE应该是什么样子,然后复制并运行此代码以查看有效的计时器:

String text = String.format(TIME_FORMAT, 
        TimeUnit.MILLISECONDS.toHours(millis) % 24,
        TimeUnit.MILLISECONDS.toMinutes(millis) % 60,
        TimeUnit.MILLISECONDS.toSeconds(millis) % 60);
timerLabel.setText("Time passed: " + text);

编辑:没有NetBeans构建器垃圾的代码:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.concurrent.TimeUnit;

import javax.swing.*;

@SuppressWarnings("serial")
public class SimpleTimer extends JPanel {
    private static final String TIME_FORMAT = "%02d:%02d:%02d";
    public static final int TIMER_DELAY = 100;
    private static final int PREF_W = 300;
    private static final int PREF_H = 100;
    private long startTime;
    private Timer myTimer;
    private JLabel timerLabel = new JLabel("00:00:00");
    private JCheckBox fastChkBox = new JCheckBox("Run Artificially Fast", false);

    public SimpleTimer() {
        JPanel centerPanel = new JPanel(new GridBagLayout());
        centerPanel.add(new JButton(new RestartAction("Restart", KeyEvent.VK_R)));
        centerPanel.add(fastChkBox);

        JPanel topPanel = new JPanel();
        topPanel.add(new JLabel("Time passed: "));
        topPanel.add(timerLabel);

        setLayout(new BorderLayout());
        add(topPanel, BorderLayout.PAGE_START);
        add(centerPanel, BorderLayout.CENTER);
    }

    private class RestartAction extends AbstractAction {
        public RestartAction(String name, int mnemonic) {
            super(name);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (myTimer != null && myTimer.isRunning()) {
                myTimer.stop();
            }

            startTime = System.currentTimeMillis();
            myTimer = new Timer(TIMER_DELAY, new TimerListener());
            myTimer.start();
        }
    }

    // make it bigger
    @Override
    public Dimension getPreferredSize() {
        Dimension superSz = super.getPreferredSize();
        if (isPreferredSizeSet()) {
            return superSz;
        }
        int prefW = Math.max(superSz.width, PREF_W);
        int prefH = Math.max(superSz.height, PREF_H);
        return new Dimension(prefW, prefH);
    }


    private class TimerListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            long millis = System.currentTimeMillis() - startTime;

            if (fastChkBox.isSelected()) {
                millis *= 512;  // make time go faster
            }
            String text = String.format(TIME_FORMAT, 
                    TimeUnit.MILLISECONDS.toHours(millis) % 24,
                    TimeUnit.MILLISECONDS.toMinutes(millis) % 60,
                    TimeUnit.MILLISECONDS.toSeconds(millis) % 60);
            timerLabel.setText(text);
        }
    }

    private static void createAndShowGui() {
        SimpleTimer mainPanel = new SimpleTimer();

        JFrame frame = new JFrame("SimpleTimer");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

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