How to ignore the event dispatch thread allows this program to work?

How I tried to find out if I can answer this question earlier today . I realized that I do not quite understand Event Dispatch Thread ( EDT ). Googling confirmed and helped with this and clarified why I didn’t . ( This may also be relevant to understanding.)

The code sets the GUI, and later (as in the previous question) updates the text field until the flag is removed.

I have a few questions / queries.

  • Please explain why the code below works fine if both calls (before swingInit and doIt ) are outside the invokeLater block (as shown), since both calls affect or request a GUI but are not executed on the EDT (are they?). Isn't that an attractive failure?

  • The code also runs if the swingInit call is inside and doIt outside invokeLater . So swingInit runs on EDT, but shouldn't doIt not run on EDT? (I was surprised that it worked. Should I be?)

  • I understand why it hangs if doIt is inside invokeLater , no matter where swingInit : the goal of invokeLater is ONLY to initialize the GUI (on the right?).

  • Should doIt triggered (possibly from an event) on the EDT, but certainly not inside the invokeLater block?

(The history of the EDT concept is interesting. This was not always the case. See the link above to “why I don't understand this.”)

 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()); }; } 
+7
java event-dispatch-thread invokelater
source share
2 answers

Taking each of your markers:

  • The code runs in the main thread - EDT runs in parallel. swingInit returns after building the user interface, which is then under EDT control, allowing dotIt to do its job in parallel in the main thread

  • A similar situation, as indicated above, but here you guarantee the construction of the user interface on EDT (as recommended by Oracle ),

  • A long task is placed in the EDT, not allowing it to show (if it is placed before swingIt ), or drawing and interaction (if placed after). the purpose of invokeLater is ONLY to initialize the GUI The goal is to put secure Swing calls in streaming mode on the EDT. If in the main method I recommend using SwingUtilities.invokeAndWait

  • If you want to update an interface like this, think about it with SwingTimer .

Running an EDT-specific, non-stream safe code outside the EDT does not guarantee failure, but it causes a failure (through conflicts when two (or more) threads try to update data at the same time).

I once spent hours tracking a cryptic NullPointerException , only to realize that this is a LookAndFeel problem whose calls were not in the EDT. Lesson learned.

+3
source share
 static void doIt(){ while(flag) tf.setText(getInfo()); }; 

This busy loop inside doIt binds the GUI thread (spinning in this loop), which will cause the GUI to freeze.

You really have not explained what you mean by “works fine”, but I assume that the problem you are seeing.

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

+2
source share

All Articles