2012-06-13 49 views
3

好日子,SwingUtilities類的invokeLater GUI更新JList的

我讀過一些其他的堆棧溢出帖子和其他教程,但按鈕開始一個漫長的過程後,我不能讓我的GUI正確更新。我附上了我所遇到的問題的完整代碼。注意,如果您運行代碼,則JList會在最後一次更新,而不是for循環的每次迭代。

import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.DefaultListModel; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JList; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 


public class theframe extends JFrame implements ActionListener 
{ 
    private JList list; 
    private DefaultListModel listmodel; 
    private JButton start; 

    public theframe() 
    { 
     listmodel = new DefaultListModel(); 
     list = new JList(listmodel); 
     start = new JButton("Start"); 

     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setSize(500,500); 
     setVisible(true); 

     list.setPreferredSize(new Dimension(200,200)); 

     start.addActionListener(this); 
     JPanel p = new JPanel(); 
     p.add(start); 
     p.add(list); 

     this.add(p); 
    } 

    public static void main(String[] args) 
    { 
     theframe frame = new theframe(); 

    } 

    @Override 
    public void actionPerformed(ActionEvent arg0) 
    { 
     if(arg0.getSource() == start) 
     { 
      for(int i=0;i<10;i++) 
      { 
       SwingUtilities.invokeLater(new Runnable() 
       { 
        @Override 
        public void run() 
        { 
         // the JList should update one by one 
         listmodel.addElement("Start pushed "); 
        } 
       }); 



       try 
       { 
            //This thread sleep simulates a long job 
        Thread.sleep(300); 
       } 
       catch (InterruptedException e) 
       { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

任何幫助將不勝感激。

回答

4

你這裏的問題是,你已經從EDT調用invokeLater方法(事件指派線程)的事實。

從EDT調用方法actionPerformed所以會發生的是sleep調用剛剛停止了EDT本身:您可以想象這不是應該如何工作的,沒有EDT運行意味着沒有GUI更新。

由於這是一項耗時的任務,因此您應該在Thread/Runnable中實施它,以便可以並行執行它,然後從其他線程調用invokeLater

喜歡的東西:

class LongProcess extends Thread { 
    public void run() { 
    for (int i = 0; i < 10; ++i) { 
     SwingUtilities.invokeLater(...); 
     Thread.sleep(300); 
    } 
    } 
} 

void actionPerformed(ActionEvent e) { 
    LongProcess process = new LongProcess(); 
    process.start(); 
} 
+0

傑克打我的答案,而我打字吧。所以我只需+1他的,因爲這正是我想說的:)只是一個附加說明,應該在線程中使用'SwingUtilities.invokeLater()'來更新Swing/AWT組件。 –

+0

謝謝@Jack和george_h!非常感激!我不明白美國東部時間表的行動來自美國東部時間,但我想現在是有道理的。感謝您及時的回覆! – Matthew

4

將在事件調度線程上調用actionPerformed方法。在EDT上調用Thread.sleep可防止更新您的GUI。由於您的GUI無法更新,因此您的JList在項目添加到它之前不會重新繪製,直到您的循環退出。您可能應該使用SwingWorker。 (SwingWorker tutorial.