我试图制作一个计数器,每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秒运行一次,对吗?看起来有点慢......这里有什么问题?
编辑:已发布完整代码。
答案 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);
}
}
}