Java 有没有在JFrame中生成计时器的方法?

Java 有没有在JFrame中生成计时器的方法?,java,swing,timer,Java,Swing,Timer,我在做游戏。在BorderLayoutNorth中,我想在您播放时显示计时器。当您丢失时,在JOptionPane.showMessage对话框中显示播放时间。获胜时,在JOptionPane.showMessageDialog中显示获胜的最佳时间 我知道如何使用JOptionPane.showMessageDialog,但我不知道java中是否有生成计时器、获取值、设置值等的方法。 谢谢如果有人需要更多信息或其他信息,请告诉我……您正在寻找一种方法,以了解某件事情需要多长时间。在编程中,通常不

我在做游戏。在BorderLayoutNorth中,我想在您播放时显示计时器。当您丢失时,在JOptionPane.showMessage对话框中显示播放时间。获胜时,在JOptionPane.showMessageDialog中显示获胜的最佳时间

我知道如何使用JOptionPane.showMessageDialog,但我不知道java中是否有生成计时器、获取值、设置值等的方法。
谢谢如果有人需要更多信息或其他信息,请告诉我……

您正在寻找一种方法,以了解某件事情需要多长时间。在编程中,通常不是计时器

您可能希望在开始时记录时间,然后在结束时再次记录时间,并计算差值以获得所用的时间

解释如何将其转换为秒


编辑:瓦肯有一个很好的观点。更值得信赖,因为它能够适应用户对系统时间的更改,并提供更高的分辨率。但请注意,正如它所说的:该方法提供纳秒精度,但不一定是纳秒分辨率,即值的变化频率-除了分辨率至少与currentTimeMillis的分辨率一样好外,不作任何保证。这是一个关于纳米时间的讨论。

您正在寻找一种方法来确定某件事情需要多长时间。在编程中,通常不是计时器

您可能希望在开始时记录时间,然后在结束时再次记录时间,并计算差值以获得所用的时间

解释如何将其转换为秒


编辑:瓦肯有一个很好的观点。更值得信赖,因为它能够适应用户对系统时间的更改,并提供更高的分辨率。但请注意,正如它所说的:该方法提供纳秒精度,但不一定是纳秒分辨率,即值的变化频率-除了分辨率至少与currentTimeMillis的分辨率一样好外,不作任何保证。这是一个关于纳米时间的讨论。

首先要注意的是

Swing是一个单线程环境,也就是说,与UI的所有交互都应该在事件调度线程的上下文中执行。同样,您不应该阻止EDT,因为这将阻止它处理新事件,包括重新绘制请求

为此,最简单的方法是使用javax.swing.Timer之类的东西,它允许您按照在EDT上下文中执行的常规间隔安排重复回调

有关更多详细信息,请参阅

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.concurrent.TimeUnit;
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 CountDownTimer {

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

    public CountDownTimer() {
        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 TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        private JLabel label;
        private long startTime = -1;
        private long timeOut = 10;

        public TestPane() {

            label = new JLabel("...");
            final Timer timer = new Timer(500, new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {


                    if (startTime == -1) {
                        startTime = System.nanoTime();
                    } else {
                        long endTime = startTime + TimeUnit.SECONDS.toNanos(10);
                        long time = System.nanoTime();

                        if (time < endTime) {
                            long timeLeft = (endTime - time);
                            label.setText(Long.toString(TimeUnit.NANOSECONDS.toSeconds(timeLeft)) + " seconds");
                        } else {
                            label.setText("Time out");
                            ((Timer) e.getSource()).stop();
                        }
                        revalidate();
                        repaint();
                    }
                }
            });
            timer.setInitialDelay(0);
            timer.start();

            setLayout(new GridBagLayout());
            add(label);

        }

    }

}

首先要注意的是

Swing是一个单线程环境,也就是说,与UI的所有交互都应该在事件调度线程的上下文中执行。同样,您不应该阻止EDT,因为这将阻止它处理新事件,包括重新绘制请求

为此,最简单的方法是使用javax.swing.Timer之类的东西,它允许您按照在EDT上下文中执行的常规间隔安排重复回调

有关更多详细信息,请参阅

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.concurrent.TimeUnit;
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 CountDownTimer {

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

    public CountDownTimer() {
        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 TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        private JLabel label;
        private long startTime = -1;
        private long timeOut = 10;

        public TestPane() {

            label = new JLabel("...");
            final Timer timer = new Timer(500, new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {


                    if (startTime == -1) {
                        startTime = System.nanoTime();
                    } else {
                        long endTime = startTime + TimeUnit.SECONDS.toNanos(10);
                        long time = System.nanoTime();

                        if (time < endTime) {
                            long timeLeft = (endTime - time);
                            label.setText(Long.toString(TimeUnit.NANOSECONDS.toSeconds(timeLeft)) + " seconds");
                        } else {
                            label.setText("Time out");
                            ((Timer) e.getSource()).stop();
                        }
                        revalidate();
                        repaint();
                    }
                }
            });
            timer.setInitialDelay(0);
            timer.start();

            setLayout(new GridBagLayout());
            add(label);

        }

    }

}

应该使用System.nanoTime,而不是System.currentTimeMillis,它用于日历时间,而不是经过的时间事实上,您可以通过更改计算机的时钟来修改System.currentTimeMillis的输出。我看不到该问答中列出的任何警告,除非你使用的是早于WinXP SP2的windows版本。纳米时代的讨论似乎都不太可信,因为许多讨论都没有提供支持其主张的链接。总而言之,它似乎是一种可靠的测量时间的方法。应该使用System.nanoTime,而不是System.currentTimeMillis,它用于日历时间,而不是经过的时间。事实上,您可以通过更改计算机的时钟来修改System.currentTimeMillis的输出。我看不到该问答中列出的任何警告,除非你使用的是早于WinXP SP2的windows版本。纳米时代的讨论似乎都不太可信,因为许多讨论都没有提供支持其主张的链接。总而言之,它似乎是一种可靠的时间测量方法。