0

I have read this article on the EDT (Event Dispatch Thread) javaworld.com which shows how to correctly setup a Swing GUI on the EDT and put long running tasks which modify the GUI inside Runnables.

It all makes sense however the example program (I pasted below) where the only modification I made is a Thread.sleep(6000) to simulate a long lag makes the interface irresponsive for some seconds.

Am I missing something?

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class ViewPage
{

    public static void main(String[] args)
    {
        Runnable r;
        r = new Runnable()
        {
            @Override
            public void run()
            {
                final JFrame frame = new JFrame("View Page");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                JPanel panel = new JPanel();
                panel.add(new JLabel("Enter URL"));
                final JTextField txtURL = new JTextField(40);
                panel.add(txtURL);
                frame.getContentPane().add(panel, BorderLayout.NORTH);
                final JTextArea txtHTML = new JTextArea(10, 40);
                frame.getContentPane().add(new JScrollPane(txtHTML),
                        BorderLayout.CENTER);
                ActionListener al;
                al = new ActionListener()
                {
                    public void actionPerformed(ActionEvent ae)
                    {
                        txtURL.setEnabled(false);
                        Runnable worker = new Runnable()
                        {
                            public void run()
                            {
                                InputStream is = null;
                                try
                                {
                                    URL url = new URL(txtURL.getText());
                                    is = url.openStream();
                                    final StringBuilder sb;
                                    sb = new StringBuilder();
                                    int b;
                                    while ((b = is.read()) != -1)
                                    {
                                        sb.append((char) b);
                                    }
                                    Runnable r = new Runnable()
                                    {
                                        public void run()
                                        {
                                            try
                                            {
                                                Thread.sleep(6000);
                                            }
                                            catch (InterruptedException ex)
                                            {
                                                Logger.getLogger(ViewPage.class.getName()).log(Level.SEVERE, null, ex);
                                            }
                                            txtHTML.setText(sb.toString());
                                            txtURL.setEnabled(true);
                                        }
                                    };
                                    try
                                    {
                                        EventQueue.invokeAndWait(r);
                                    }
                                    catch (InterruptedException ie)
                                    {
                                    }
                                    catch (InvocationTargetException ite)
                                    {
                                    }
                                }
                                catch (final IOException ioe)
                                {
                                    Runnable r = new Runnable()
                                    {
                                        public void run()
                                        {
                                            txtHTML.setText(ioe.getMessage());
                                            txtURL.setEnabled(true);
                                        }
                                    };
                                    try
                                    {
                                        EventQueue.invokeAndWait(r);
                                    }
                                    catch (InterruptedException ie)
                                    {
                                    }
                                    catch (InvocationTargetException ite)
                                    {
                                    }
                                }
                                finally
                                {
                                    Runnable r = new Runnable()
                                    {
                                        public void run()
                                        {
                                            txtHTML.setCaretPosition(0);
                                            txtURL.setEnabled(true);
                                        }
                                    };
                                    try
                                    {
                                        EventQueue.invokeAndWait(r);
                                    }
                                    catch (InterruptedException ie)
                                    {
                                    }
                                    catch (InvocationTargetException ite)
                                    {
                                    }
                                    if (is != null)
                                    {
                                        try
                                        {
                                            is.close();
                                        }
                                        catch (IOException ioe)
                                        {
                                        }
                                    }
                                }
                            }
                        };
                        new Thread(worker).start();
                    }
                };
                txtURL.addActionListener(al);
                frame.pack();
                frame.setVisible(true);
            }
        };
        EventQueue.invokeLater(r);
    }
}

1 Answer 1

2

Am I missing something?

Yes.

Runnable is just an interface not another thread. Here with this line you are wrapping the call to execute later in the Event Dispatch Thread.

EventQueue.invokeLater(r); // you can use SwingUtilities.invokeLater(r) too 

Then you call

Thread.sleep(6000);

This is executed in EDT and make irresponsive the gui until finish.

For long task you should use another threads or SwingWorker and for short task with some repetitions SwingTimer. Read about Concurrency in Swing

Sign up to request clarification or add additional context in comments.

2 Comments

Can you confirm there's a mistake in the javaworld article where he says "Listing 4 differs from Listing 3 in that it creates a worker thread to read the HTML document via a runnable.", indeed he actually creates a Runnable and not a worker thread, and also where he says "The result is a responsive UI because the EDT is never delayed." it actually is because of the reason you just described.
Listing 4 contains this line: new Thread(worker).start(); However, any tutorial whose example code has 4 levels of nested anonymous classes shows pretty poor teaching skills. Also, he warns never to call invokeAndWait from the event thread, but the documentation clearly states that it will immediately throw an error, rather than hang the thread. You are better off learning from an official tutorial like this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.