简体   繁体   English

SwingUtilities使用JList调用更新GUI更新

[英]SwingUtilities invokeLater GUI update with JList

Good day, 美好的一天,

I've read a few other stack overflow postings and other tutorials, but I can't get my GUI to update correctly after a button starts a long process. 我已经阅读了其他一些堆栈溢出帖子和其他教程,但是在按钮启动一个漫长的过程后,我无法正确地更新GUI。 I've attached the full code of the problem that I am having. 我附上了我遇到的问题的完整代码。 Notice if you run the code, the JList gets updated all at once at the end instead of every iteration of the for loop. 请注意,如果运行代码,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();
                }
            }
        }
    }
}

Any help would be greatly appreciated. 任何帮助将不胜感激。

The actionPerformed method will be called on the Event Dispatch Thread. 将在Event Dispatch Thread上调用actionPerformed方法。 Calling Thread.sleep on the EDT stops it from updating your GUI. 在EDT上调用Thread.sleep阻止它更新GUI。 Since your GUI cannot update, your JList will not repaint itself when items are added to it until after your loop exits. 由于您的GUI无法更新,因此在您的循环退出之前,在添加项目时,您的JList不会重新绘制。

You should probably be using a SwingWorker . 您可能应该使用SwingWorker ( SwingWorker tutorial. ) SwingWorker教程。

Your problem here is the fact that you are calling the invokeLater method already from the EDT ( Event Dispatching Thread ). 你的问题是你已经从EDT( 事件调度线程 )调用了invokeLater方法。

The method actionPerformed is called from the EDT so what happens is that the sleep call just stops the EDT itself: you can imagine that this is not how it should work, no EDT running means no GUI updates. 从EDT调用actionPerformed方法,因此sleep调用只会停止EDT本身:您可以想象这不是它应该如何工作,没有EDT运行意味着没有GUI更新。

Since it's a time consuming task you should implement it in a Thread / Runnable so that you can execute it in parallel and then call the invokeLater from this other thread. 由于这是一个耗时的任务,你应该在Thread / Runnable实现它,这样你就可以并行执行它,然后从另一个线程调用invokeLater

Something like: 就像是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM