tags:

views:

56

answers:

3

Hi,

I have a question regarding quick initialization of swing components. At the start of my swing application I have a window that pops up with buttons that allow the user to do a variety of things. Is there I way that I can quickly launch that first window and load the rest of the UI (such as other frames and dialogs) in the background so that there is isn't that initial delay.

Thanks,

A: 

Yes. Ish. You could do something similar to:

public static void main(String [] args) {
    // Construct main Frame on Swing EDT thread
    Thread thread = new Thread() {
        public void run() {
             JFrame mainFrame = new JFrame();
             mainFrame.setVisible();
             // etc.
        }
     };

     SwingUtilities.invokeLater(thread);

     // now the background init stuff
     Class.forName("com.yourcompany.view.Dialog1");
     Class.forName("com.yourcompany.view.WizardGUI");
     Class.forName("com.yourcompany.view.SecondaryFrame");

     // Here all the views are loaded and initialized
 }
Rekin
Unfortunately I keep getting a ConcurrentModificationException with Nimbus UI. Not sure why.
Dave
Could You post stack trace?
Rekin
Swing is not thread safe. There should be a single thread cating the gui.
extraneon
invokeLater takes a Runnable as an argument; no need for a Thread.
Maurice Perry
Yeah it was actually my fault with the ConcurrentModificationException. I didn't take enough care with the threads I was creating and they wanted to call something that wasn't yet ready to be called. It works now.
Dave
+1  A: 

Is Swing thread safe?

r3st0r3
Swing is not Thread Safe
Romain Hippeau
It is not, but a frame and it's components can be created in any thread, but as soon as the frame is first shown, all access to swing components must be done by the swing event handling thread.
Maurice Perry
+1  A: 

There really is no good solution to this, it is one of the drawbacks of Java. That being said keep reading for my idea.

There are two parts to loading a class.

  1. The JVM loads the class file into the ClassLoader when it is needed.
  2. The JIT compiles and optimizes the code the first time the path is run.

You can do what rekin suggests, which is to eagerly load the UI classes before they are needed. That will only partially solve your problem, because you are only getting some of the classes. This will also have the disadvantage of taking up a lot more memory and even the classes in the class loader will be garbage collected if needed.

In order to avoid some of the hassles you are getting with the Reflection Approach. One method you could try is in your windows make sure the constructor does not display a window, instead have another method that would display the window called init(), Then have a separate Thread from main call create a new on each of the Windows you want to preload.
Do not save the reference to the window.

In the real code you would call the constructor and then init() for each window you wanted to display. This would give you the best possible scenario as far as performance, because now you are loading the classes as well as running the constructor code. Of course the size of the program in memory will be bloated.

public static void main(String [] args) {
    // Construct main Frame on Swing EDT thread
    Thread thread = new Thread() {
        public void run() {
          // now the background init stuff
          new com.yourcompany.view.Dialog1();
          new com.yourcompany.view.WizardGUI();
          new com.yourcompany.view.SecondaryFrame();
         // Here all the views are loaded and initialized
        }
     };

     JFrame mainFrame = new JFrame();
     mainFrame.setVisible();
     // etc.
 }
Romain Hippeau
Yep this works well.
Dave