Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 计时器/秒表GUI_Java_Swing_User Interface_Timer - Fatal编程技术网

Java 计时器/秒表GUI

Java 计时器/秒表GUI,java,swing,user-interface,timer,Java,Swing,User Interface,Timer,我正在尝试制作一个简单的java应用程序,它可以计算时间,并能够停止和启动计时器。但是,标签不会更新,当我按start时,它会冻结 你能帮我找出问题所在吗 package random; import javax.swing.JFrame; public class Timer { boolean shouldCount=false; int int_sec=0; int int_min=0; int int_mil=0; public static void main(String[] a

我正在尝试制作一个简单的java应用程序,它可以计算时间,并能够停止和启动计时器。但是,标签不会更新,当我按start时,它会冻结

你能帮我找出问题所在吗

package random;

import javax.swing.JFrame;

public class Timer {
boolean shouldCount=false;
int int_sec=0;
int int_min=0;
int int_mil=0;
public static void main(String[] args) {
    TimeFrame t = new TimeFrame();
    JFrame f = new JFrame("Timer");
    f.setSize(300,200);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setLocationRelativeTo(null);
    f.getContentPane().add(t);
    f.setVisible(true);
}

public void count(){
    TimeFrame t = new TimeFrame();
    if(shouldCount){
        long now = System.currentTimeMillis();
        while(true){
            if(System.currentTimeMillis()-now>=100){
                now=System.currentTimeMillis();
                String sec = Integer.toString(int_sec);
                String min = Integer.toString(int_min);
                String mil = Integer.toString(int_mil);
                t.update(sec,int_sec,min,mil,int_mil);
                int_mil++;
                if(int_mil>9){
                    int_mil=0;
                    int_sec++;
                    if(int_sec>=60){
                        int_sec=1;
                        int_min++;
                    }
                }
            }
        }
    }
}
}
这里是TimeFrame.java

    package random;

    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JLabel;
    import javax.swing.JPanel;

    public class TimeFrame extends JPanel{
    JLabel time = new JLabel("Time goes here", JLabel.CENTER);
    Timer t = new Timer();
    JButton pause = new JButton ("Pause");
     JButton start = new JButton ("Start");
    public TimeFrame(){

         start.addActionListener(new starts());
         pause.addActionListener(new starts());
         add(time);
         add(start);
         add(pause);
    }
    public void update(String sec,int s, String min,String mil,int m){
        if (s<=10){
            sec="0"+sec;
        }
        System.out.println(min+":"+sec+","+mil);
        time.setText(min+":"+sec+","+mil);

    }
    public class starts implements ActionListener{
        public void actionPerformed(ActionEvent event){
            if(event.getSource() == start){
                t.shouldCount=true;
            }else{
                t.shouldCount=false;
            }
            t.count();
        }
    }
}
随机包装;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入javax.swing.JButton;
导入javax.swing.JLabel;
导入javax.swing.JPanel;
公共类时间框架扩展了JPanel{
JLabel time=newjlabel(“时间在这里”,JLabel.CENTER);
定时器t=新定时器();
JButton pause=新JButton(“暂停”);
JButton start=新JButton(“start”);
公共时间表(){
addActionListener(newstarts());
pause.addActionListener(newstarts());
加上(时间);
添加(开始);
添加(暂停);
}
公共无效更新(字符串秒、整数s、字符串最小值、字符串mil、整数m){

如果(s问题是应用程序中只有一个线程,那么至少应该有两个线程:一个用于更新文本的UI,另一个用于计算时间

如果只有一个线程,它将挂起在while(true)循环中,Swing永远无法更新视图

我使用两个线程重构了您的代码:

  • 一次计数直到时间结束,并更新字段以将时间保留在内存中

  • 另一个是使用java.util.Timer#scheduleAtFixedRate()方法的,该方法每100毫秒调用一次以更新视图

  • Timer.java
    (避免像JavaAPI中那样命名类)

    TimeFrame
    (我更愿意称之为
    TimePanel
    ,因为它扩展了
    JPanel

    公共类时间框架扩展JPanel{
    JLabel时间;
    定时器t;
    按钮暂停;
    按钮启动;
    公共时间表(){
    t=新计时器(此);
    时间=新的JLabel(“时间在这里”,JLabel.CENTER);
    暂停=新按钮(“暂停”);
    开始=新的JButton(“开始”);
    addActionListener(newstarts());
    pause.addActionListener(newstarts());
    加上(时间);
    添加(开始);
    添加(暂停);
    java.util.Timer updateTimer=new java.util.Timer();
    updateTimer.scheduleAtFixedRate(新TimerTask(){
    @凌驾
    公开募捐{
    t、 更新(单位秒、单位分钟、单位英里);
    }
    }, 0, 100);
    }    
    公共无效更新(整数s、整数分钟、整数m){
    字符串秒=整数。toString(s);
    字符串最小值=整数。toString(分钟);
    字符串mil=整数。toString(m);
    
    如果(s问题在于while循环绑定到接口线程。当您单击开始按钮时,它调用Timer.count(),然后进入无限循环,导致接口被卡住,永远不会更新

    使用java.util.Timer类更好的假设可能高估了该类针对此特定问题的功能。它不包含暂停方法,您必须在想要暂停计时器时重新创建计时器,这可能会给时间加总带来一些困难

    我要做的是让你的计时器实现runnable接口,并使用一个线程来记录你当前的时间

    请注意,我将字段设置为私有。将字段设置为私有(如果应该的话)并使用getter和setter授予对它们的访问权限是正确的做法。例如:getCurrentTime()

    Timer.java:

    package random;
    
    import javax.swing.JFrame;
    
    public class Timer implements Runnable {
    
        private Thread runThread;
        private boolean running = false;
        private boolean paused = false;
        private TimeFrame timeFrame;
        private long summedTime = 0;
    
        public Timer(TimeFrame timeFrame) {
            this.timeFrame = timeFrame;
        }
    
        public static void main(String[] args) {
            TimeFrame t = new TimeFrame();
            JFrame f = new JFrame("Timer");
            f.setSize(300,200);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setLocationRelativeTo(null);
            f.getContentPane().add(t);
            f.setVisible(true);
        }
    
        public void startTimer() {
            running = true;
            paused = false;
            // start the thread up
            runThread = new Thread(this);
            runThread.start();
        }
    
        public void pauseTimer() {
            // just pause it
            paused = true;
        }
    
        public void stopTimer() {
            // completely stop the timer
            running = false;
            paused = false;
        }
    
        @Override
        public void run() {
            long startTime = System.currentTimeMillis();
            // keep showing the difference in time until we are either paused or not running anymore
            while(running && !paused) {
                timeFrame.update(summedTime + (System.currentTimeMillis() - startTime));
            }
            // if we just want to pause the timer dont throw away the change in time, instead store it
            if(paused)
                summedTime += System.currentTimeMillis() - startTime;
            else 
                summedTime = 0;
        }
    }
    
    TimeFrame.java:

    package random;
    
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    
    public class TimeFrame extends JPanel{
        private JLabel time = new JLabel("Time goes here", JLabel.CENTER);
        private Timer timer;
        private JButton pause = new JButton ("Pause");
        private JButton start = new JButton ("Start");
    
        public TimeFrame(){
            timer = new Timer(this);
             start.addActionListener(new starts());
             pause.addActionListener(new starts());
             add(time);
             add(start);
             add(pause);
        }
        public void update(long dT){
            // convert milliseconds into other forms
            time.setText(String.valueOf((dT/6000)%1000)+":"+String.valueOf((dT/1000)%1000)+","+String.valueOf((dT)%1000));
        }
        public class starts implements ActionListener{
            public void actionPerformed(ActionEvent event){
                if(event.getSource() == start){
                    timer.startTimer();
                }else{
                    timer.pauseTimer();
                }
            }
        }
    }
    

    为什么不使用a而不是
    while
    循环?另外,您可能正试图从另一个线程更新gui线程,这将导致问题。我认为存在
    runLater()
    thread thing,可以让您从其他线程安全地更新gui线程。谢谢,除了暂停按钮外,它工作得很好。我读了代码,我认为它可以工作,但它没有,你知道为什么吗?是的,要使它工作,有一些事情需要更改。我会研究它,但你也可以在设置“应该计数”时自己尝试如果设置为true或false,则不会影响while true循环,因为从未计算该条件。请将该条件放入while循环中,并从ActionListener中删除t.count(),因为它将创建一个新线程。
    package random;
    
    import javax.swing.JFrame;
    
    public class Timer implements Runnable {
    
        private Thread runThread;
        private boolean running = false;
        private boolean paused = false;
        private TimeFrame timeFrame;
        private long summedTime = 0;
    
        public Timer(TimeFrame timeFrame) {
            this.timeFrame = timeFrame;
        }
    
        public static void main(String[] args) {
            TimeFrame t = new TimeFrame();
            JFrame f = new JFrame("Timer");
            f.setSize(300,200);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setLocationRelativeTo(null);
            f.getContentPane().add(t);
            f.setVisible(true);
        }
    
        public void startTimer() {
            running = true;
            paused = false;
            // start the thread up
            runThread = new Thread(this);
            runThread.start();
        }
    
        public void pauseTimer() {
            // just pause it
            paused = true;
        }
    
        public void stopTimer() {
            // completely stop the timer
            running = false;
            paused = false;
        }
    
        @Override
        public void run() {
            long startTime = System.currentTimeMillis();
            // keep showing the difference in time until we are either paused or not running anymore
            while(running && !paused) {
                timeFrame.update(summedTime + (System.currentTimeMillis() - startTime));
            }
            // if we just want to pause the timer dont throw away the change in time, instead store it
            if(paused)
                summedTime += System.currentTimeMillis() - startTime;
            else 
                summedTime = 0;
        }
    }
    
    package random;
    
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    
    public class TimeFrame extends JPanel{
        private JLabel time = new JLabel("Time goes here", JLabel.CENTER);
        private Timer timer;
        private JButton pause = new JButton ("Pause");
        private JButton start = new JButton ("Start");
    
        public TimeFrame(){
            timer = new Timer(this);
             start.addActionListener(new starts());
             pause.addActionListener(new starts());
             add(time);
             add(start);
             add(pause);
        }
        public void update(long dT){
            // convert milliseconds into other forms
            time.setText(String.valueOf((dT/6000)%1000)+":"+String.valueOf((dT/1000)%1000)+","+String.valueOf((dT)%1000));
        }
        public class starts implements ActionListener{
            public void actionPerformed(ActionEvent event){
                if(event.getSource() == start){
                    timer.startTimer();
                }else{
                    timer.pauseTimer();
                }
            }
        }
    }