代码之家  ›  专栏  ›  技术社区  ›  Roman

SimplesGUI倒计时应该如何工作?

  •  1
  • Roman  · 技术社区  · 15 年前

    我正在写simples gui倒计时。我在网上找到了一些密码,但对我来说已经太花哨了。我尽量保持简单。所以,我只想让一个窗口说“你还有10秒钟”。每秒的秒数应该从10减少到0。我写了一个密码。我想我已经接近工作方案了。但我还是错过了一些东西。你能帮我查出怎么了吗?这是我的代码:

    import javax.swing.*;
    
    public class Countdown {
    
        static JLabel label;
    
        // Method which defines the appearance of the window.   
        private static void showGUI() {
            JFrame frame = new JFrame("Simple Countdown");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JLabel label = new JLabel("Some Text");
            frame.add(label);
            frame.pack();
            frame.setVisible(true);
        }
    
        // Define a new thread in which the countdown is counting down.
        static Thread counter = new Thread() {
            public void run() {
                for (int i=10; i>0; i=i-1) {
                    updateGUI(i,label);
                    try {Thread.sleep(1000);} catch(InterruptedException e) {};
                }
            }
        };
    
        // A method which updates GUI (sets a new value of JLabel).
        private static void updateGUI(final int i, final JLabel label) {
            SwingUtilities.invokeLater(new Runnable(i,label) {
    
                public Runnable(int i, JLabel label) {
                    this.i = i;
                    this.label = label;
                }
    
                public void run() {
                    label.setText("You have " + i + " seconds.");
                }
    
            });
        }
    
        // The main method (entry point).
        public static void main(String[] args) {
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    showGUI();
                    //counter.start();
                }
            });
            //counter.start();
        }
    
    }
    

    关于这个代码,我有几个具体的问题:

    1. 我应该把 counter.start(); ?(在我的代码中,我把它放在两个地方。哪一个是正确的?)

    2. 为什么编译器会抱怨runnable的构造函数?它说我有一个无效的方法声明,我需要指定返回的类型。

    补充: 我做了建议的修正。然后我执行代码并得到:

    Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at Worker.run(Worker.java:12)
    

    在第12行的worker.java中,我有: label.setText("You have " + i + " seconds."); .

    2 回复  |  直到 13 年前
        1
  •  2
  •   Kiril    15 年前

    呼叫 counter.start() 在可运行文件中:

    // The main method (entry point).
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                showGUI();
                counter.start();
            }
        });
    }
    

    您真的想要一个特定的调用顺序,如果您将它放在线程之外,那么计数器将在GUI存在之前启动,并且它将在您身上失败。

    对于第二个问题:

    // A method which updates GUI (sets a new value of JLabel).
    private static void updateGUI(final int i, final JLabel label) {
        SwingUtilities.invokeLater(new Worker(i, label));
    }
    

    这是工人:

    import javax.swing.JLabel;
    
    public class Worker implements Runnable{
        private int i;
        private JLabel label;
        public Worker(int i, JLabel label) {
            this.i = i;
            this.label = label;
        }
    
        public void run() {
            label.setText("You have " + i + " seconds.");
        }
    }
    

    现在你的主要任务是:

    // The main method (entry point).
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Countdown.showGUI();
                counter.start();
            }
        });
    }
    

    更新:
    或者如果您仍然想使用匿名模式,那么:

    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.SwingUtilities;
    
    public class Countdown {
    
        static JLabel label;
    
        // Method which defines the appearance of the window.   
        public static void showGUI() {
            JFrame frame = new JFrame("Simple Countdown");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            label = new JLabel("Some Text");
            frame.add(label);
            frame.pack();
            frame.setVisible(true);
        }
    
        // Define a new thread in which the countdown is counting down.
        public static Thread counter = new Thread() {
            public void run() {
                for (int i=10; i>0; i=i-1) {
                    updateGUI(i,label);
                    try {Thread.sleep(1000);} catch(InterruptedException e) {};
                }
            }
        };
    
        // A method which updates GUI (sets a new value of JLabel).
        private static void updateGUI(final int i, final JLabel label) {
            SwingUtilities.invokeLater( 
                new Runnable() {
                    public void run() {
                        label.setText("You have " + i + " seconds.");
                    }
                }
            );
        }
    }
    
        2
  •  1
  •   Andrew Thompson    13 年前

    答案中的匿名示例非常有效。

    对于第一个答案,计数器工作,但没有显示GUI,并且每秒钟都会出现以下异常

    Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
            at com.aramco.ecc.licenseoptimizer.gui.Worker.run(Worker.java:23)
            at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
            at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
            at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
            at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
            at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
            at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
            at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
            at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)