views:

196

answers:

2

In Java, to create and show a new JFrame, I simply do this:

public static void main(String[] args)
{
   new MyCustomFrameClass().setVisible(true);
}

However, I have seen many people doing it like this:

public static void main(String[] args)
{
  EventQueue.invokeLater(new Runnable()
  {
       public void run()
       {
           new MyCustomFrameClass().setVisible(true);
       }
  });
}

Why? Are there any advantages?

+3  A: 

This line is modifying a Swing component since your custom frame is a subclass of JFrame:

new MyCustomFrameClass().setVisible(true);

Generally, you should never modify a Swing component unless you are on the Event Dispatch Thread (EDT).

The following code will run whatever is in the Runnable on the EDT.

EventQueue.invokeLater(Runnable);

Now, the setVisible(true) call will be on the EDT as it should.

jjnguy
I meant to create an instance of a JFrame subclass, not directly a JFrame. Sorry for the confusion. (I updated my original post)
asmo
The same still applies to any subclass of any swing component. It doesn't change anything. (@asmo)
jjnguy
Thanks for the clarification.
asmo
+4  A: 

The rules governing what needs to be performed on the EDT (I see "EDT" more often used than "Event Queue") have changed during Java's lifetime. And everytime the "rules" changed, Sun advised doing more and more "GUI related" work on the EDT.

Why do people run Java GUI’s on the EDT?

  • Because the official guidelines advise doing so.

  • Because doing so will help dodge a lot of threading bugs related to the GUI.

Note, and this is not very well known, that the EDT actually does crash once in a while, because Swing itself has a few bugs. Every non-trivial Swing application is using Swing APIs that have, well, bugs and hence once in a while the EDT dies.

You never see it and it isn't a cause of concerns, because when the EDT dies it is automagically restarted.

Basically, do all GUI-related stuff on the EDT and do all lenghty operations outside the EDT (as to not block the EDT).

EDIT you asked for an example as to how to run a lenghty operation outside the EDT. There are several ways to do this. In the simplest case, you simply create and start a new Thread, from the EDT. Here's one example: the listener callback shall be called when the user clicks on a button, we know that this shall happen on the EDT...

    JButton jb = ...
    jb.addActionListener( new ActionListener() {
        public void actionPerformed( final ActionEvent e ) {
          final Thread t = new Thread( new Runnable() {
           public void run() {
             // this shall get executed, after start() has been called, outside the EDT    
             }
           });
           t.start();
        }
    } );

For more complicated examples, you want to read on SwingWorker, etc.

NoozNooz42
How can I do operations outside the EDT if they need to be started from my GUI? (button event, etc) Also, do I need to use the EDT only for the main frame? If the user opens another JFrame from the main frame (for example an option window), do I need to start it on the EDT?
asmo
@asmo: I'll edit my question to give an example
NoozNooz42
@asmo: you need the work on the EDT for *everything* related to the GUI (so in your *"option window"* example, yup, that needs to be done on the EDT too).
NoozNooz42
It's unlikely that the EDT would crash. Unchecked exceptions thrown in EDT dispatch are caught, dumped and the thread goes on. There is a mechanism for the thread to exit and later for a new one to replace it, but that's so the process can exit without calling `System.exit` if no windows are realised and there are no other non-daemon threads.
Tom Hawtin - tackline
If I create and show the option window like this **"new OptionFrame().setVisible(true);"** from an actionPerformed method that's called from the main JFrame, do I need to wrap the **"new OptionFrame().setVisible(true);"** in the invokeLater() method to put it in the EDT or is it already in the EDT?
asmo
Teaching spawning Threads to do background work is too simple - it must be governed. Otherwise this program grows up, has lots of these, reaches production status, and has race conditions all over with unfixable bugs.
Thorbjørn Ravn Andersen
@Tom Hawtin - tackline: I dispute that. This is not the behavior I see in IntelliJ IDEA, nor in my applications (non-trivial Swing app). I started a new question here, with a code example, which I need explanation about: http://stackoverflow.com/questions/3020757
NoozNooz42
@NoozNooz42 It does indeed seem that the behaviour has changed in the current Sun/Oracle implementation (to something complicated).
Tom Hawtin - tackline