invokeAndWait method in SwingUtilities
Please explain invokeAndWait() method in SwingUtilities.I am unable to understand this. Explain it very clearly. It would be of great help if you try out with an example.
Edited to add @noob's expansion of the question:
What's not clear about this?
Here's a modified usage example:
import javax.swing.SwingUtilities;
public class InvokeAndWaitStuff
{
public static void main(String[] args)
{
final Runnable doHelloWorld = new Runnable() {
public void run() {
System.out.println("Hello World on " + Thread.currentThread());
}
};
Thread appThread = new Thread() {
public void run() {
try {
SwingUtilities.invokeAndWait(doHelloWorld);
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("Finished on " + Thread.currentThread());
}
};
appThread.start();
}
}
Output:
Hello World on Thread[AWT-EventQueue-0,6,main]
Finished on Thread[Thread-0,5,main]
And why is this important?:
Causes doHelloWorld.run() to be executed synchronously on the AWT event dispatching thread. This call blocks until all pending AWT events have been processed and (then) doHelloWorld.run() returns. This method should be used when an application thread needs to update the GUI.
As far as I can tell, this is basically a bottleneck that forces GUI updates to be executed synchronously by a single thread, rather than asynchronously by multiple threads, which can potentially be unsafe.
To understand what invokeAndWait()
does, you first need to understand the event/thread model of Swing.
Basically, everything that affects the GUI in any way must happen on a single thread. This is because experience shows that a multi-threaded GUI is impossible to get right.
In Swing, this special GUI thread is called the Event Dispatch Thread, or EDT. It is started as soon as a Swing top-level component is displayed, and it's bascially a worker thread that has a FIFO queue of event objects that it executes one after another.
When a Swing GUI needs to be drawn or updated, the JRE places an event on the EDT queue. User actions that cause listeners to be called start as events on the EDT queue. And (this is this is the important part) everything your program does that changes the GUI (like registering listeners, adding/removing GUI components or changing model data that the GUI displays) must be placed in the EDT queue, or the GUI can get corrupted.
And now for the finish: invokeAndWait()
places the Runnable
you pass to it into the EDT event queue and waits until the EDT has executed it. This should be used when a non-GUI thread needs to do something that affects the GUI, but also needs to wait until it is actually done before it can continue. If you just want to do something that affects the GUI but do not care when it is finished, you should instead use invokeLater()
.
I had a similar problem in a JTable. The program was blocked somewhere in "scrollRectToVisible" method. I have replaced the call by wrapping it in an invokeLater call. The invokeAndWait did not resolve my block problem.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
table.scrollRectToVisible(r);
}
});