Non-modal JDialog is not painted and blocks the GUI

I have developed a GUI that's basically a JFrame with a JDesktopPane.

The user can, via a menu item, pop up a JDialog that contains some JLists and then select some value from it. Once he/she has done the selection and clicks on OK, the dialog disappears (data processing is then done in the main GUI) and comes back once a specific event has happened. The user then selects other data and so on, until he/she clicks on Cancel, which definitely disposes of the JDialog.

The graphics of the JDialog are build in the class constructor, which does a pack() but does not make the dialog visible yet. The dialog appears only when doSelection() is called.

/** Called the first time when user selects the menu item, and then

when a specific event has happened. */

public Data[] doSelection(){

dialog.setVisible(true);

// ... Code that reacts to user's input. Basically, the ActionListener

// added to the buttons retrieves the user's selection and calls

// dialog.setVisible(false) if OK is clicked, or calls dialog.dispose()

// if Cancel is clicked.

// ...

}

Now, everything works fine if the JDialog is modal, but if I make it non-modalonly the window decorations of the JDialog are painted, and the control doesn't return to the main GUI. Calling doLayout() or repaint() on the doSelection() has no effect. How can this be fixed?

I hope I have been able to explain the problem satisfactorily, I could not create a suitable SSCCEE to show you. Thanks in advance for any hint.

[1871 byte] By [java_knighta] at [2007-11-27 8:15:14]
# 1

> but if I make it non-modal

Then code after the setVisible(...) method executes immediately. It does not wait for the dialog to be closed.

Add a System.out.println(..) statement after the setVisble(..) statement and you will see what I mean.

So you need to change your design. Basically the code that closes the dialog needs to invoke some code in your main program when it closes.

camickra at 2007-7-12 19:59:59 > top of Java-index,Desktop,Core GUI APIs...
# 2

> Then code after the setVisible(...) method executes

> immediately. It does not wait for the dialog to be

> closed.

Yes I know. This is because the dialog is non-modal. Basically I'd like to force it to lay out its content before proceeding to the next instructions.

java_knighta at 2007-7-12 19:59:59 > top of Java-index,Desktop,Core GUI APIs...
# 3

> Basically I'd like to force it to lay out its content

> before proceeding to the next instructions.

Forcing a layout is done via a pack() call. You do not need to make the dialog/frame visible to lay it out. The pack() call is synchronous, so it returns after the GUI hierarchy is completely laid out.

Greets,

Mike

MikePa at 2007-7-12 19:59:59 > top of Java-index,Desktop,Core GUI APIs...
# 4
> Forcing a layout is done via a pack() call. You do> not need to make the dialog/frame visible to lay it> out.I already call pack() in the constructor, and instructions after pack() are happily executed. That's what is puzzling me.
java_knighta at 2007-7-12 19:59:59 > top of Java-index,Desktop,Core GUI APIs...
# 5
Post more code from doSelection function.My guess would be that you're blocking the event dispathing thread.
Rodney_McKaya at 2007-7-12 19:59:59 > top of Java-index,Desktop,Core GUI APIs...
# 6
Yes, that's also what I thought. I apologize but I have to work on something different right now, so I need to pause this discussion momentarily. I'll be back asap. In the meantime, thanks to all, and see you again later!
java_knighta at 2007-7-12 19:59:59 > top of Java-index,Desktop,Core GUI APIs...
# 7

Ok, I've taken some time to think about this problem and I've modified the code a bit.

Now the dialog shows itself and is responsive (i.e. its JLists can be operated), but the Ok button does not close the dialog as I'd want. I believe that I'm messing up things about threading, and the operations in actionPerformed() should be carried out in another thread, if possible.

Thanks in advance for any hint / suggestion / comment / insult.

private Data[] selection;

/** Constructor */

public MyDialog() {

// ... Here is the code that builds the dialog...

dialog.setModal(false);

dialog.pack();

// Note that the dialog is not visible yet

}

public Data[] doSelection() {

operatorAnswer = NONE_YET;

dialog.setVisible(true);

while (operatorAnswer == NONE_YET) {

try {

wait();

} catch (InterruptedException e) { }

return (operatorAnswer == OK ? selection : null);

}

public void actionPerformed(ActionEvent evt) {

if (okButton.equals(evt.getSource())) {

operatorAnswer = OK;

retrieveSelection();

dialog.setVisible(false);

}

else if (cancelButton.equals(evt.getSource())) {

operatorAnswer = CANCEL;

dialog.dispose();

}

}

private void retrieveSelection() {

// ... Here is the code that retrieves selected data from the dialog's JLists

// and stores it in the "selection" private array...

notifyAll();

}

java_knighta at 2007-7-12 19:59:59 > top of Java-index,Desktop,Core GUI APIs...
# 8

One week later I still have no idea what you are trying to do or what the problem is.

If you need further help then you need to create a "Short, Self Contained, Compilable and Executable, Example Program (SSCCE)",

see http://homepage1.nifty.com/algafield/sscce.html,

that demonstrates the incorrect behaviour, because I can't guess exactly what you are doing based on the information provided.

Don't forget to use the "Code Formatting Tags",

see http://forum.java.sun.com/help.jspa?sec=formatting,

so the posted code retains its original formatting.

camickra at 2007-7-12 19:59:59 > top of Java-index,Desktop,Core GUI APIs...
# 9

i see what u want to do,

how about if you do this

1. you create a aclass file extended jdialog1

and at that dialog had

private Set userChoice

and a public function to return userChoice example

public function Set getUserChoice(){

return userChoice

}

and okbutton and cancel button

2. at jframe you must do is

jdialog mydialog=jdialog1();

mydialog.setmodal(true);

mydialog.setvisible(true);

Set uchoice=mydialog.getUserChoice();

3. don't forget to fill set everytime user make a choice.

4. don't forget to reward duke

suryanto_soa at 2007-7-12 19:59:59 > top of Java-index,Desktop,Core GUI APIs...
# 10
My question is this, why do you want the dialog to be non-modal if you still want to block to wait for the answer?Anyway your problem lies in the fact that you're calling wait() on the EDT effectively blocking it from processing anything else (including your non-modal dialog).
dwga at 2007-7-12 19:59:59 > top of Java-index,Desktop,Core GUI APIs...
# 11

> My question is this, why do you want the dialog to be

> non-modal if you still want to block to wait for the

> answer?

Because the user wants to be able to operate other functions of the GUI.

However, I've been thinking that non-modality is perhaps not the best option in this case, and that I should instead add a functionality to hide the dialog via a call to setVisible(false).

> Anyway your problem lies in the fact that you're

> calling wait() on the EDT effectively blocking it

> from processing anything else (including your

> non-modal dialog).

Hence, can this be done in a different way? Maybe with a SwingWorker?

Thanks for all your hints.

java_knighta at 2007-7-12 19:59:59 > top of Java-index,Desktop,Core GUI APIs...
# 12

> i see what u want to do,

> how about if you do this

> (...)

> 2. at jframe you must do is

> jdialog mydialog=jdialog1();

> mydialog.setmodal(true);

> mydialog.setvisible(true);

> Set uchoice=mydialog.getUserChoice();

This is a modal dialog. I want the dialog to be non-modal.

java_knighta at 2007-7-12 19:59:59 > top of Java-index,Desktop,Core GUI APIs...