3

I'm still having problems with blank JOptionPanes. Based on research at SO and in Java Docs, this obviously has something to do with not using the EDT. My question is how exactly do the EDT and its methods apply to JOptionPane? For example, the terminal error output makes it quite clear that the JOptionPane below is not run on the EDT. What's missing specifically, and how does something like Runnable fit in?

import javax.swing.*;
public class PaneDemo
{
public static void main(String[] args)
{
    final String[] TEXT ={
            //message
            "Hello, World!",
            //title
            "Greeting"};//end TEXT
    showMyPane(TEXT);
}//end main
public static void showMyPane(final String[] TEXT)
{
    JOptionPane.showMessageDialog(null, TEXT[0], TEXT[1], 
        JOptionPane.INFORMATION_MESSAGE);
    if(!SwingUtilities.isEventDispatchThread())
    {
        System.err.println("Err: GUI failed to use EDT.");
    }//end if(!SwingUtilities.isEventDispatchThread())
}//end showMyPane
}//end class PaneDemo

An answer suggested adding invokeLater. That doesn't seem to render very well in BlueJ, however.

BlueJ Screenshot

Also isEventDispatchThread() is still returning the error in the terminal. Is that simply because it is now in the wrong location?

Matt B
  • 1,813
  • 2
  • 17
  • 20

1 Answers1

11

You can create JOptionPane on the Event Dispatch Thread like this:

enter image description here

  final String[] TEXT = {
        //message
        "Hello, World!",
        //title
        "Greeting"};//end TEXT

     ...

    /**
     * Create GUI and components on Event-Dispatch-Thread
     */
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
                JOptionPane.showMessageDialog(null, TEXT[0] 
                      + "\n is on EDT: " + SwingUtilities.isEventDispatchThread(), TEXT[1],
                        JOptionPane.INFORMATION_MESSAGE);
        }
    });

Have a look at the Lesson: Concurrency in Swing it should help you understand what its all about

UPDATE:

as per comment you should initiate the JOptionPane on the EDT on each call in showPane(...) method like so:

   public static void showMyPane(final String[] TEXT) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JOptionPane.showMessageDialog(null, TEXT[0] 
                      + "\n is on EDT: " + SwingUtilities.isEventDispatchThread(), TEXT[1],
                        JOptionPane.INFORMATION_MESSAGE);
            }
        });
    }//end showMyPane

    public static void main(String[] args) {
        final String[] TEXT = {
            //message
            "Hello, World!",
            //title
            "Greeting"};//end TEXT
        showMyPane(TEXT);
    }
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
  • 3
    `"However if you only want to show a JOptionPane without any JFrame etc you don't need to use Event-Dispatch-Thread"`, actually, yeah, I think you do. – Hovercraft Full Of Eels Oct 26 '12 at 19:59
  • @David If EDT is not required, what is causing the blank JOptionPanes? I've read Concurrency in Swing about Integer.MAX_VALUE times already. – Matt B Oct 26 '12 at 20:00
  • You can also your SwingUtilities.invokeAndWait if you want to block the execution of the code until the user has responded to the dialog – MadProgrammer Oct 26 '12 at 20:00
  • 1
    David: only if its API says that it is. Last time I looked, this wasn't mentioned. – Hovercraft Full Of Eels Oct 26 '12 at 20:01
  • @HovercraftFullOfEels you are right just checked it now sorry another link mislead me – David Kroukamp Oct 26 '12 at 20:02
  • @MattB sorry I was incorrect about that, as for blank `JOptionPane`s I'm not sure, post an [SSCCE](http://sscce.org). See my edited post – David Kroukamp Oct 26 '12 at 20:06
  • @David No worries! As for an SSCCE, it seems to occur entirely randomly, so the code I posted already is the best I can do. – Matt B Oct 26 '12 at 20:08
  • @Andrew It'll only block with in the context if the EDT, it will allow the calling thread to continue running – MadProgrammer Oct 26 '12 at 20:14
  • So how does the code posted for this answer fit with the code I posted in the question? In other words, what changes do I now make to `showMyPane()`? – Matt B Oct 26 '12 at 20:24
  • @MattB see update. BTW the Blank `JOptionPane` might have happened due to creating multiple `JOptionPane`s one after another without use of EDT – David Kroukamp Oct 26 '12 at 20:32
  • 1
    @MadProgrammer not good idea to use `invokeAndWait`, if is there once time started EDT, `invokeLater` is safiest, otherwise have to test `isEvent...`, [because invokeAndWait lock EDT if is active](http://stackoverflow.com/questions/10769895/when-exactly-is-the-event-dispatch-thread-started/10770381#10770381) to try to call `invokeAndWait` on EDT – mKorbel Oct 26 '12 at 20:37
  • 1
    @mKorbel I agree, but if you've already made the choice to sync the call back to the EDT (because you've checked `isEventDispatchingThread`) and you're interested in the return result of the call, `invokeAndWait` is one of the best choices. – MadProgrammer Oct 26 '12 at 20:45
  • Just curious, what is the reason for `javax.swing.SwingUtilities` rather than simply `SwingUtilities`? The class compiles either way. I haven't tried to run it yet though. – Matt B Oct 26 '12 at 20:48
  • @MattB it basically like an inline import, you wont have to still add the `imports javax.swing...` statement. You can optionally clarify the import globally just delete the `javax.swing.` part and then use this at top of class after package declaration `import javax.swing.SwingUtilities;`. – David Kroukamp Oct 26 '12 at 20:52
  • @MattB see my update you have the `SwingUtilities.isEventDispatchThread()` outside of the `SwingUtilities.invokeLater(...)` thus it returns false – David Kroukamp Oct 26 '12 at 21:40