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

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

我声明“timer”的行中的“10”应该导致“listener”每 1/100 秒运行一次,对吗?看起来有点慢...这里出了什么问题?

编辑:发布完整代码。

最佳答案

Swing Timer 并不是 100% 准确的,1/100 可能会突破它的极限。考虑使用 Swing Timer,但显示通过获取时间计算得出的绝对时间差。

例如,

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

}

关于Java - 使用 Swing Timer 每 1/100 秒执行一项任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33489705/

相关文章:

java - 初始化后如何更改JTable?

javascript - 我正在尝试为我的网站制作一个倒计时器,并且我已完成所有编码,但计时器没有显示。我是在 Dreamweaver 中做的

javascript - JQuery 向后计时器不应在页面刷新时停止(倒计时器)

java - 如何在jsp中打印图像(大量)

java - 如何指定抽象父字段的子类

java - 如何在txt文件中查找特定值或字符串并将其放入java中的表中?

swift - 构建一个小型计时器应用程序,为什么应用程序计时器不会停止两个标签?

java - 关闭打开的 hibernate session (如果存在)

java - 写入文件时出现奇怪的字符 (Mac) (Java)

java - 如何更改 JComboBox 显示区域的外观