2011-08-05 55 views
2

我是Swing的新手,我試圖這樣做:如何在Swing中進行一些處理時重新繪製標籤?

按下JButton時,程序將開始迭代數百個項目,每秒處理1秒,每完成一項更新標籤以顯示已處理的物品數量。

問題是,標籤的文本不會更新,直到週期完成迭代所有項目爲止。

我在網上搜索,顯然這是因爲它在同一個線程中運行,所以我創建了一個新線程來處理數據並更新要在標籤中使用的變量(已處理文件的數量)。

但它沒有奏效。然後,我甚至製作了另一個線索,我從之前的一個線索開始,重新繪製標籤。仍然沒有用。

的代碼是這樣的:

btnNewButton.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      try { SwingUtilities.invokeLater(validateFiles); } 
}); } 

Runnable validateFiles = new Runnable() { 

    @Override 
    public void run() { 
       while(x_is_not_100) { 
         processLoadsOfStuff(); 
         label.setText(x); } 
      } 
}; 

你能幫助我嗎?

回答

7

簡單 - 使用一個SwingWorker。欲瞭解更多信息,請閱讀教程Tasks that Have Interim Results


下面是將使用JLabel顯示來自計數到一個非常通用的例子 -

public final class SwingWorkerDemo { 
    private static JLabel label = 
     new JLabel(String.valueOf(0), SwingConstants.CENTER); 

    public static void main(String[] args){ 
     SwingUtilities.invokeLater(new Runnable(){ 
      @Override 
      public void run() { 
       createAndShowGUI();    
      } 
     }); 

     JLabelSwingWorker workerThread = new JLabelSwingWorker(); 
     workerThread.run(); 
    } 

    private static void createAndShowGUI(){ 
     final JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     frame.add(label); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    private static class JLabelSwingWorker extends SwingWorker<Void, Integer>{ 
     @Override 
     protected Void doInBackground() throws Exception { 
      for(int i = 1; i < 31; i++){ 
       Thread.sleep(1000); 
       publish(i); 
      } 
      return null; 
     } 

     @Override 
     protected void process(List<Integer> integers) { 
      Integer i = integers.get(integers.size() - 1); 
      label.setText(i.toString()); 
     } 
    } 
} 
+0

因爲我記得很好的化身(...)+1 – mKorbel

5

後臺處理必須在一個單獨的線程來完成。但標籤更新必須在事件派發線程中完成。

所以,你的代碼應該是這樣的:

btnNewButton.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent e) { 
     // start a new thread for the background task 
     new Thread(validateFiles).start(); 
    }); 
} 

Runnable validateFiles = new Runnable() { 

    @Override 
    public void run() { 
      while(x_is_not_100) { 
        processLoadsOfStuff(); 
        // use SwingUtilities.invokeLater so that the label update is done in the EDT: 
        SwingUtilities.invokeLater(new Runnable() { 
         @Override 
         public void run() { 
          label.setText(x); 
         } 
        }); 
      } 
    }; 

但你可能想使用SwingWorker類,它是專門做,在一個簡單的方法。它的文檔做得非常好,幷包含示例。

相關問題