java - Java 中的 Swing 计时器秒表

标签 java swing timer stopwatch

有人可以为我提供一个使用不断更新的 JLabel 的 Java Swing Timer 秒表 GUI 示例吗?我不熟悉使用 @Override,所以请不要建议其中包含该代码,除非绝对必要(我已经完成了其他 Swing 计时器,例如系统时钟,但没有它)。

谢谢!

编辑:根据@VGR的请求,这是我使用 Swing Timer 的基本时钟的代码:

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.FlowLayout;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.Font;

public class basic_clock extends JFrame
{
    JLabel date, time;

    public basic_clock()
    {
        super("clock");

        ActionListener listener = new ActionListener()
        {
            public void actionPerformed(ActionEvent event)
            {
                Calendar current = Calendar.getInstance();
                current.setTime(new Date());
                date.setText((current.get(Calendar.MONTH) + 1) +"/" +current.get(Calendar.DATE) +"/" +current.get(Calendar.YEAR));
                String timeStr = String.format("%d:%02d:%02d", current.get(Calendar.HOUR), current.get(Calendar.MINUTE), current.get(Calendar.SECOND));
                time.setText(timeStr);                
            }
        };

        date = new JLabel();
        time = new JLabel();

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

        add(date);
        add(time);

        date.setFont(new Font("Arial", Font.BOLD, 64));
        time.setFont(new Font("Arial", Font.BOLD, 64));

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

    public static void main(String args[])
    {

        basic_clock c = new basic_clock();
        c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

显然,我需要与 Calendar 对象不同的东西,因为我想跟踪精确到 1/100 秒的分钟和秒,而不是日期/月/年/小时/分钟/秒。

最佳答案

I did Google for it, but I wasn't understanding the code that I found

那么你就有一个更大的问题了。您如何期望我们中的任何人为您提供一个您可以理解的示例?

秒表在概念上非常简单,它只是自启动以来已经过去的时间量。当您希望能够暂停计时器时,就会出现问题,因为您需要考虑计时器已运行的时间加上自上次启动/恢复以来的时间。

另一个问题是,大多数计时器仅保证最短时间,因此不精确。这意味着您不能只是不断地将计时器的延迟量添加到某个变量中,您最终会得到一个漂移值(不准确)

这是一个非常简单的示例,它所做的只是提供一个开始和停止按钮。每次启动秒表时,都会再次从 0 开始。

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SimpleStopWatch {

    public static void main(String[] args) {
        new SimpleStopWatch();
    }

    public SimpleStopWatch() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new StopWatchPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class StopWatchPane extends JPanel {

        private JLabel label;
        private long lastTickTime;
        private Timer timer;

        public StopWatchPane() {
            setLayout(new GridBagLayout());
            label = new JLabel(String.format("%04d:%02d:%02d.%03d", 0, 0, 0, 0));

            timer = new Timer(100, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    long runningTime = System.currentTimeMillis() - lastTickTime;
                    Duration duration = Duration.ofMillis(runningTime);
                    long hours = duration.toHours();
                    duration = duration.minusHours(hours);
                    long minutes = duration.toMinutes();
                    duration = duration.minusMinutes(minutes);
                    long millis = duration.toMillis();
                    long seconds = millis / 1000;
                    millis -= (seconds * 1000);
                    label.setText(String.format("%04d:%02d:%02d.%03d", hours, minutes, seconds, millis));
                }
            });

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weightx = 1;
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.insets = new Insets(4, 4, 4, 4);
            add(label, gbc);

            JButton start = new JButton("Start");
            start.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (!timer.isRunning()) {
                        lastTickTime = System.currentTimeMillis();
                        timer.start();
                    }
                }
            });
            JButton stop = new JButton("Stop");
            stop.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    timer.stop();
                }
            });

            gbc.gridx = 0;
            gbc.gridy++;
            gbc.weightx = 0;
            gbc.gridwidth = 1;
            add(start, gbc);
            gbc.gridx++;
            add(stop, gbc);
        }

    }

}

添加暂停功能并不难,它只需要一个额外的变量,但我会将其留给您来解决。

关于java - Java 中的 Swing 计时器秒表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33487186/

相关文章:

java - 碰撞检测java给出意想不到的结果

android - CountDownTimer 未取消 --- 在 Cancel() 后继续运行

javascript - 在 div 中获取一个 span innerHTML

java - 在普通类中获取 startActivityForResult() 的结果

java - 访问子类中的父类(super class)变量/方法

java - J2ME显示内容

java - 客户端的html文件加密

java - swing组件和awt事件的问题

java - JTextPane#getText() 不返回组件的文本

java - 如何在应用程序运行时将多个 textView 更改为特定的日期和时间