I have a simple groovy script that from its main thread of execution needs to display some dialog boxes to the user.
My swing knowledge is limited and rusty but I recall reading about the need to be careful to keep GUI stuff on the event-dispatching thread (EDT).
If I just call the static JOptionPane.showMessageDialog
method from my main thread am I right in assuming this would violate the correct practice of keeping GUI stuff on the EDT?
Should I actually be using the swing.utils.invokeAndWait method such as in the following example code?
void showHelloThereDialog()
throws Exception {
Runnable showModalDialog = new
Runnable() {
public void run() {
JOptionPane.showMessageDialog(
myMainFrame, "Hello There");
}
};
SwingUtilities.invokeAndWait
(showModalDialog);
}
Now the above doesn't do anything to make values from something other than a message dialog available after invokeAndWait completes.
Presumably the fact that groovy 'closures' implement Runnable will make for simpler code than above.
Is invokeAndWait required? And if so would someone please give an example of correct implementation to get the result of something like a confirmDialog using groovy?
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.
Since Swing is not thread-safe by design, it's designer did provide couple of utility methods in SwingUtilities class to update any Swing component from a thread other thread Event Dispatcher Thread.
invokeAndWait . Both of these methods take a single argument: the Runnable that defines the new task. Their only difference is indicated by their names: invokeLater simply schedules the task and returns; invokeAndWait waits for the task to finish before returning.
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.
A call to one of JOptionPane
's showXXXDialog() is BLOCKING until the user selects ok/cancel/etc. In general you do not put such slow blocking insturctions on the Event Dispatch Thread (EDT) as a rule because every single other GUI component will freeze. So, a gut instinct to not put it on the EDT is good, but it is also wrong. The reason is as stated by some others, the method creates GUI components and this should always be done on the EDT. But what about the blocking? You will notice that even if you do run it on the EDT, it works fine. The reason is found inside the source code. The JOptionPane
class creates a Dialog object and then calls show()
followed by dispose()
, the first of which is what blocks the thread. If you read the comments (or javadoc), you will see that it says this about the method:
If the dialog is modal and is not already visible, this call will not return until the dialog is hidden by calling hide or dispose. It is permissible to show modal dialogs from the event dispatching thread because the toolkit will ensure that another event pump runs while the one which invoked this method is blocked.
So, it is perfectly safe to run JOptionPane
on the EDT despite it blocking. Obviously, it is safe to call Dialog's show()
method off the EDT but the same is not true for JOptionPane
because its methods are creating GUI components, adding listeners, accessing other containers when modal and blocking input to them, etc. You do not want all of this done off the EDT because it is not thread-safe and there could be problems. Admittedly, I have never seen problems when using JOptionPane
off the EDT and so the chances seem low, but they are most certainly possible. Passing in a null for the container of the dialog and only giving immutable objects (like String
s) as arguments to the fields will significantly reduce (maybe even eliminate as far as I know) the chance of something bad happening because all relevant GUI components are made and accessed within the same thread while they are not visible. But, you should just be safe and put it on the EDT. It is not that difficult to call SwingUtilities.invokeAndWait()
.
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