SwingUtilities invokeLater GUI update with JList

java, multithreading, swing, swingutilities, user-interface

Solution

Your problem here is the fact that you are calling the `invokeLater` method already from the EDT (Event Dispatching Thread).

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.

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.

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

Problem

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.

Original source