Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the (event-dispatch) thread safe usage for JOptionPane.showMessageDialog and swing.utils.invokeAndWait?

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?

like image 346
Alex Stoddard Avatar asked Mar 30 '11 20:03

Alex Stoddard


People also ask

What is event dispatcher thread in Swing?

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.

Is Swingworker thread safe?

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.

What is the difference between invokeAndWait and invokeLater?

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.

What is SwingUtilities invokeLater () used for?

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.


1 Answers

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 Strings) 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().

like image 140
David Avatar answered Oct 12 '22 23:10

David