DSlomer64
DSlomer64

Reputation: 4283

How does ignoring the event dispatch thread allow this program to work?

As I tried to see if I could answer this question earlier today. I realized that I don't fully understand the Event Dispatch Thread (EDT). Googling both confirmed and helped with that and clarified why I don't. (This might also be relevant to understanding.)

The code sets up a GUI and later (as in the earlier question) updates a text field until a flag is unset.

I have several questions/requests.

(The history of the EDT concept is interesting. It was not always thus. See link above to "why I don't" understand it.)

import static java.awt.EventQueue.invokeLater;
import java.awt.event.*;
import javax.swing.*;

public class Whatever 
{
  static boolean flag = true;
  static JTextField tf = new JTextField("Hi",20);
  static JPanel p = new JPanel();
  static JFrame f = new JFrame();
  static JButton b = new JButton("End");

  public static void main(String[] args)
  {
    swingInit();

    invokeLater
    (
      new Runnable()
      {
        @Override
        public void run() 
        {
    //    swingInit();
    //    doIt();
        }
      }
    ); 
   doIt();      
  } 

  static void swingInit()
  {
     b.addMouseListener
    (
        new MouseAdapter()
        {
          @Override
          public void mouseClicked(MouseEvent e)
          {
            flag = false;
            JOptionPane.showMessageDialog(null,"Clicked... exiting");
            System.exit(0);
          }
        }
    );

    p.add(tf);
    p.add(b);
    f.add(p);
    f.setVisible(true);
    f.pack();
    f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
  }

  static String getInfo(){
    return "Hello... " + Math.random();
  }

  static void doIt(){
    while(flag)     
      tf.setText(getInfo());
  }; 
}

Upvotes: 7

Views: 566

Answers (2)

copeg
copeg

Reputation: 8348

Taking each of your bullet points:

  • The code is launched on the Main thread - the EDT is run in parallel. swingInit returns after constructing the UI which is then under control of the EDT, allowing dotIt to do its thing in parallel on the main thread

  • Similar situation as above, but here you are guaranteeing construction of the UI on the EDT (as recommended by Oracle).

  • A long running task is placed onto the EDT, preventing it from showing (if placed before swingIt) or painting and interaction (if placed after). the purpose of invokeLater is ONLY to initialize the GUI The purpose is to place non-thread safe Swing calls onto the EDT. If within the main method, I would recommend using SwingUtilities.invokeAndWait

  • If you wish to update the UI like this, consider doing so with a SwingTimer.

Running EDT specific, non-thread safe code outside the EDT doesn't guarantee failure, but it does invite failure (via conflicts when two (or more) threads attempt to update data at the same time).

I once spent hours tracking down a mysterious NullPointerException, only to realize it was a LookAndFeel issue whose calls were not on the EDT. Lesson learned.

Upvotes: 3

DaoWen
DaoWen

Reputation: 33029

static void doIt(){
  while(flag)     
    tf.setText(getInfo());
}; 

That busy-loop inside doIt ties up the GUI thread (spinning in that loop), which will cause the GUI to hang.

You didn't actually explain what you mean by "runs fine", but I'm assuming that's the problem that you're seeing.

You might want to use a Swing Timer to do something like what you do in the loop.

Upvotes: 2

Related Questions