Java - 使用Swing Timer每1/100秒执行一次任务

时间:2015-11-03 00:54:05

标签: java swing timer

我试图制作一个计数器,每1/100秒计算一次,直到程序关闭,但它看起来比这慢一点。这就是我所拥有的:

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.FlowLayout;
import javax.swing.*;

public class counterTest extends JFrame
{
    JLabel label;
    long counter = 0;
    String counterStr;

    public counterTest()
    {
        super("counter");

        ActionListener listener = new ActionListener()
        {
            public void actionPerformed(ActionEvent event)
            {
                counter++;
                counterStr = Long.toString(counter);
                label.setText(counterStr);                
            }
        };

        label = new JLabel();

        setLayout(new FlowLayout());
        setSize(100,100);
        setResizable(false);
        setVisible(true);

        add(label);

        javax.swing.Timer timer = new javax.swing.Timer(10, listener);
        timer.setInitialDelay(0);
        timer.start();
    }

    public static void main(String args[])
    {
        counterTest c = new counterTest();
        c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

" 10"在我宣布"计时器"的行中应该导致"听众"每1/100秒运行一次,对吗?看起来有点慢......这里有什么问题?

编辑:已发布完整代码。

1 个答案:

答案 0 :(得分:4)

Swing Timer的构建不是100%准确,而1/100可能会推动它的极限。考虑使用摆动计时器,但显示绝对时间差,通过获取时间计算。

如,

private class MyTimerListener implements ActionListener {
    private long startTime = 0;

    public void reset() {
        startTime = System.currentTimeMillis();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        long time = System.currentTimeMillis();
        long delta = (time - startTime) / 10L;
        label.setText(String.valueOf(delta));
    }
}

好的,我的迷你程序:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class MyTimer2 extends JPanel implements GuiTimer {
    private static final String TIME_FORMAT = "%03d:%03d";
    private static final int EXTRA_WIDTH = 50;
    private JLabel timerLabel = new JLabel();
    private TimerControl timerControl = new TimerControl(this);

    public MyTimer2() {
        JPanel topPanel = new JPanel();
        topPanel.add(new JLabel("Time:"));
        topPanel.add(timerLabel);

        JPanel centerPanel = new JPanel();
        centerPanel.add(new JButton(timerControl.getStartAction()));
        centerPanel.add(new JButton(timerControl.getStopAction()));

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

        setDeltaTime(0);
    }

    @Override
    public void setDeltaTime(int delta) {
        int secs = (int) delta / 1000;
        int mSecs = (int) delta % 1000;
        timerLabel.setText(String.format(TIME_FORMAT, secs, mSecs));
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension superSz = super.getPreferredSize();
        if (isPreferredSizeSet()) {
            return superSz;
        }
        int prefW = superSz.width + EXTRA_WIDTH;
        int prefH = superSz.height;
        return new Dimension(prefW, prefH);
    }

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

        JFrame frame = new JFrame("MyTimer2");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }
}

interface GuiTimer {
    public abstract void setDeltaTime(int delta);
}

@SuppressWarnings("serial")
class TimerControl {
    private static final int TIMER_DELAY = 10;
    private long startTime = 0;
    private long pauseTime = 0;
    private Timer timer;
    private GuiTimer gui;
    private StartAction startAction = new StartAction();
    private StopAction stopAction = new StopAction();

    public TimerControl(GuiTimer gui) {
        this.gui = gui;
    }

    public Action getStopAction() {
        return stopAction;
    }

    public Action getStartAction() {
        return startAction;
    }

    enum State {
        START("Start", KeyEvent.VK_S), 
        PAUSE("Pause", KeyEvent.VK_P);
        private String text;
        private int mnemonic;

        private State(String text, int mnemonic) {
            this.text = text;
            this.mnemonic = mnemonic;
        }

        public String getText() {
            return text;
        }

        public int getMnemonic() {
            return mnemonic;
        }
    };

    private class StartAction extends AbstractAction {
        private State state;

        public StartAction() {
            setState(State.START);
        }

        public final void setState(State state) {
            this.state = state;
            putValue(NAME, state.getText());
            putValue(MNEMONIC_KEY, state.getMnemonic());
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (state == State.START) {
                if (timer != null && timer.isRunning()) {
                    return; // the timer's already running
                }
                setState(State.PAUSE);
                if (startTime <= 0) {
                    startTime = System.currentTimeMillis();
                    timer = new Timer(TIMER_DELAY, new TimerListener());
                } else {
                    startTime += System.currentTimeMillis() - pauseTime;
                }
                timer.start();
            } else if (state == State.PAUSE) {
                setState(State.START);
                pauseTime = System.currentTimeMillis();
                timer.stop();
            }
        }
    }

    private class StopAction extends AbstractAction {
        public StopAction() {
            super("Stop");
            int mnemonic = KeyEvent.VK_T;
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (timer == null) {
                return;
            }
            timer.stop();
            startAction.setState(State.START);
            startTime = 0;
        }
    }

    private class TimerListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            long time = System.currentTimeMillis();
            long delta = time - startTime;
            gui.setDeltaTime((int) delta); 
        }
    }

}