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. 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.
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.
Your problem here is the fact that you are calling the
invokeLatermethod already from the EDT (Event Dispatching Thread).The method
actionPerformedis called from the EDT so what happens is that thesleepcall just stops the EDT itself: you can imagine that this is not how it should work, no EDT running means no GUI updates.Since it’s a time consuming task you should implement it in a
Thread/Runnableso that you can execute it in parallel and then call theinvokeLaterfrom this other thread.Something like: