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.
Please explain why the code below runs fine if both calls (to swingInit
and doIt
) are outside the invokeLater
block (as shown), since both calls affect or query the GUI yet neither are executing on the EDT (are they?). Isn't that inviting failure?
Code also runs if call to swingInit
is inside and doIt
outside invokeLater
. So swingInit
is executed on the EDT, but shouldn't doIt
not executing on the EDT be a problem? (I was surprised that this worked. Should I have been?)
I guess I understand why it hangs if doIt
is inside invokeLater
regardless of where swingInit
is: the purpose of invokeLater
is ONLY to initialize the GUI (right?).
Should doIt
only be initiated (possibly from an event occurring) on the EDT but certainly not inside invokeLater
block?
(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());
};
}
The event dispatching thread (EDT) is a background thread used in Java to process events from the Abstract Window Toolkit (AWT) graphical user interface event queue.
An invokeLater() method is a static method of the SwingUtilities class and it can be used to perform a task asynchronously in the AWT Event dispatcher thread. The SwingUtilities. invokeLater() method works like SwingUtilities. invokeAndWait() except that it puts the request on the event queue and returns immediately.
SwingUtilities class has two useful function to help with GUI rendering task: 1) invokeLater(Runnable):Causes doRun. run() to be executed asynchronously on the AWT event dispatching thread(EDT). This will happen after all pending AWT events have been processed, as is described above.
You can use invokeAndWait() and invokeLater() to update a Swing component from any arbitrary thread.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With