views:

109

answers:

4

As part of a larger application, I am writing a settings class, which collects and stores user-defined settings. This class is a singleton, and is instantiated during application startup.

In order to accept user input, two different GUI frames are insantiated from within ConfigSettings.java, from a public static method, selectSettings(). Both are subclasses of JFrame. Here is the code for the instantiation of the file selection dialog:

private void selectFile() {
    SelectFileGUI fileSelector = new SelectFileGUI();
    fileSelector.setVisible(true);
    synchronized(this) {
        try {
            wait();
        }   catch(Exception e) {
            e.printStackTrace();
        }
    }
    fileSelector.dispose();
}

This works fine when the application is initially run. However, at a later point the user may alter their selected settings, including selecting a new source file. This is done by calling selectSettings() again.

The issue I'm having is that any subsequent attempt to instantiate and display these GUI components again results in a new JFrame being displayed, but with a grey background, and no buttons or other components shown. While debugging I was also failing to create new instances of SelectFileGUI directly.

What could be causing this sort of behaviour?

+2  A: 

I would check to see if the second time you call it you are using the GUI thread or calling from one of your own threads.

At the top of that method you can test for it (The AWT thread is pretty easily identifiable by name) and have it throw an exception so developers know not to call it on the wrong thread--or you can block their thread and do it in a worker thread.

Bill K
Thanks very much, you were completely right. By paying attention to the threads I now have everything sorted :)
deyur
A: 

Agree with BillK: sounds like you're calling it from outside the EDT first time around (so your call to wait() doesn't block the EDT), then from the EDT the second time around. See SwingUtilities.invokeAndWait() and/or Dialog.setModal().

Matt McHenry
+1  A: 

I don't know what is causing this behavior but in your code the following simply cannot possibly be the right way to manage dialogs (more below):

fileSelector.setVisible(true);
    synchronized(this) {
        try {
            wait();
        }   catch(Exception e) {
            e.printStackTrace();
        }
    }
    fileSelector.dispose();

Do you want your dialogs to be modal or not?

If you want them to be modal, then you simply make a blocking call like when you're invoking JColorChooser.showDialog(...) method and your return "value" is your color/file/whatever.

If you want them non-modal, then you use a callback to get your color/file. In the JColorChooser dialog example, you'd call the createDialog(...) method and use the ok/cancel listeners as callbacks.

I suggest you take a look at sun's tutorial, for example the one on color chooser, to see how to correctly display a modal (or non-modal) dialog:

http://java.sun.com/docs/books/tutorial/uiswing/components/colorchooser.html

Once again, that synchronized(this) { try { wait() ... } to manage something as simple as a file selector/dialog frame just cannot be correct.

Webinator
A: 

The consensus here is that you are breaking the rules governing the use of the AWT painting thread (the Event Dispatch Thread).
A couple things to note:

  • If your code attempts to paint your GUI components outside this painting thread, the gray dialog could be the result of a deadlock between the EDT and the thread your application is using to paint.
  • If you do get into this situation, you will experience the inability to create new dialogs as described.
  • However, as you mention that you are debugging while experiencing this problem, it might be that you have paused the EDT through your IDE.

Take a look at this tutorial for some guidelines on how use threads in a client application.

To fully appreciate the issue, it would be nice to see some more code - pertinent parts of selectSettings(), for example.

akf