2010-03-19 68 views
1

我想寫簡單的GUI倒計時。我在互聯網上找到了一些代碼,但它對我來說已經太過幻想了。我儘可能保持簡單。所以,我只想要一個窗口說「你還剩10秒」。秒數應該從10秒減少到0秒。我寫了一段代碼。我認爲我接近了工作解決方案。但我仍然錯過了一些東西。你能否請求幫助我找出問題所在?這裏是我的代碼:簡單的GUI倒計時應該如何工作?

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的構造函數?它說我有一個無效的方法聲明,我需要指定返回的類型。

新增: 我提出修改建議。在第12行我有

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

在Worker.java:label.setText("You have " + i + " seconds.");然後我執行的代碼,並獲得。

+0

只是一個評論:我不會依賴thread.wait()來等待1000毫秒。查看剩餘時間,並從中動態生成秒數。存儲啓動循環的時間,並保持查詢睡眠間隔到期的時間。 –

+0

JLabel label = new JLabel(「Some Text」); 將其更改爲 label = new JLabel(「Some Text」); 您之前沒有設置之前正在使用的字段.. –

+0

Chris Dennett,你的建議很有效。現在我有一個工作應用程序。非常感謝!但是,我沒有得到最後一個問題。如果我在「標籤」之前使用「JLabel」,我會將「標籤」作爲該方法的局部變量? – Roman

回答

2

呼叫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(); 
     } 
    }); 
} 

UPDATE:
或者,如果你還在想要使用匿名的p然後:

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."); 
       } 
      } 
     ); 
    } 
} 
1

答案中的匿名示例完美地工作。

至於第一答案,櫃檯的工作,但沒有得到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)