【问题标题】:SwingUtilities invokeLater GUI update with JListSwingUtilities invokeLater GUI update with JList
【发布时间】:2012-06-16 00:20:54
【问题描述】:

早安,

我已经阅读了一些其他堆栈溢出帖子和其他教程,但是在按钮开始一个漫长的过程后,我无法让我的 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();
                }
            }
        }
    }
}

任何帮助将不胜感激。

【问题讨论】:

    标签: java multithreading swing user-interface swingutilities


    【解决方案1】:

    您的问题是您已经从 EDT 调用 invokeLater 方法(事件调度线程)。

    actionPerformed 方法是从 EDT 调用的,所以发生的情况是 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();
    }
    

    【讨论】:

    • 杰克在我打字的时候打败了我。所以我只会 +1 他,因为这正是我要说的 :) 只是补充说明 SwingUtilities.invokeLater() 应该在线程中使用以更新 Swing/AWT 组件。
    • 谢谢@Jack 和george_h!非常感激!我不明白 actionPerformed 来自 EDT,但我想现在是有道理的。感谢您的快速回复!
    【解决方案2】:

    actionPerformed 方法将在事件调度线程上调用。在 EDT 上调用 Thread.sleep 会阻止它更新您的 GUI。由于您的 GUI 无法更新,因此您的 JList 在添加项目时不会重新绘制自身,直到您的循环退出。

    您可能应该使用SwingWorker。 (SwingWorker tutorial.)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-21
      • 1970-01-01
      相关资源
      最近更新 更多