简单的GUI倒计时应该如何工作?
我正在尝试编写简单的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(); } }
我对这段代码有几个具体的问题:
-
我应该在哪里放置
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.");
。
在runnable中调用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."); } } ); } }
答案中的匿名例子非常有效。
至于第一个答案,计数器工作,但没有显示GUI,并在每一秒出现以下exception
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)