开发者

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?


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


This should be on the EDT so invokeAndWait, or invokeLater, are required. You can tell since the code for JOptionPane.showMessageDialog eventually creates and modifies Swing components. As of Java 6, Sun says that all manipulations of Swing components (whether they have been realized or not) must be done on the EDT.

http://download.oracle.com/javase/6/docs/api/javax/swing/package-summary.html

http://www.velocityreviews.com/forums/t707173-why-does-jdk-1-6-recommend-creating-swing-components-on-the-edt.html


Take a look at groovy.swing.SwingBuilder, it encapsulates invokeAndWait and invokeLater. Your example can be written as:

import groovy.swing.SwingBuilder
import javax.swing.*
import java.awt.*

def swing = new SwingBuilder()
def myMainFrame = new Frame()

swing.edt {
    JOptionPane.showMessageDialog(
        myMainFrame, "Hello There");
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜