2012-06-13 46 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.