File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Swing / AWT / SWT and the fly likes JFrame not repainting when overlayed JDialog is closed Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "JFrame not repainting when overlayed JDialog is closed" Watch "JFrame not repainting when overlayed JDialog is closed" New topic
Author

JFrame not repainting when overlayed JDialog is closed

George Marinkovich
Ranch Hand

Joined: Apr 15, 2003
Posts: 619
I'm taking the SCJD exam, but I've decided to post this question here instead because I think it deals specifically with Swing/JFC/AWT issues. The situation is as follows:
I have a JDialog that appears over my main JFrame. The JDialog has two buttons: a "Wait Now" and a "Try Again Later." When the user selects the "Try Again Later" button the JDialog is closed and the JFrame is again the active window, and its contents appear just as they did before the JDialog was popped-up. This works according to my expectations without any problem.
If the user selects the "Wait Now" button the JDialog is closed, I change the cursor to a busy cursor, and then I make a call to wait() (hence the name, Wait Now). I would expect the JDialog to disappear (it does), I would expect to see a busy cursor (I do), and I would expect to see the original contents of the JFrame (I DON'T), and then I would expect the window to remain frozen until my thread is notified (it does). Instead what I see is the original contents of the JFrame with a greyed-out area where the JDialog was. In other words, the JFrame doesn't get repainted. Furthermore, if I iconify the JFrame in this state it comes back completely greyed out.
So my question is this: why do I have that greyed-out area where the JDialog was displayed and how can I get rid of it. I want to simply see the original contents of the JFrame while I wait for my thread to become active again.
I have tried calling repaint() on the JFrame after closing the JDialog but this doesn't seem to fix the problem.
I'm guessing that because I make my thread wait() I'm somehow interfering with the repaint() but I confess I don't understand the mechanism enough to solve the problem.
Can anyone here help?


Regards, George
SCJP, SCJD, SCWCD, SCBCD
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

If you've called wait() in an event handler, then the thread that would be doing the repainting is blocked waiting for wait() to return. Swing uses just one thread to do both painting and event handling. You should never, ever call wait() or do anything else time consuming in an event handler for this very reason.
The right thing to do is to spawn a separate thread to do the waiting. In the vent handler you should first call getGlassPane().setVisible(true) on the JFrame, set the busy cursor, then spawn the new thread. The glass pane keeps the JFrame from responding to any events. When the waiting is over, you call setGlassPane().setVisible(false) and set the normal cursor (both in a call to SwingUtilities.invokeLater(), of course) and return.


[Jess in Action][AskingGoodQuestions]
George Marinkovich
Ranch Hand

Joined: Apr 15, 2003
Posts: 619
Thank you so much for the quick response.
Let me see if I fully understand your solution:
1. My event handler makes the glass pane visible to keep the JFrame from responding to any events.
2. My event handler sets the busy cursor.
3. My event handler spawns a new thread which among other things calls wait().
4. My event handler calls SwingUtilities.invokeLater(resetMethod)
5. resetMethod makes the glass pane invisible to allow the JFrame to respond to events again, and
6. resetMethod sets the normal cursor.
So after step 2, we should have the JFrame displaying a busy cursor, and the JFrame should be unresponsive to any events.
Step 3 spawns the new thread.
After step 4, resetMethod will run which will make the JFrame responsive to events and change the cursor back to normal.
It seems to me that steps 4-6 can happen before step 3 completes (by which I mean the new thread completes its work). That is, unless I'm mistaken, step 3 can complete before step 4, before step 5, before step 6, or even after step 6. In other words, isn't step 3, since it's in it's own thread, completely independent of steps 4,5, or 6?
I understood that steps 1 and 2 display the busy cursor and make the JFrame unresponsive.
Steps 4,5,6 then make the cursor normal and make the JFrame responsive again.
But I don't want the cursor to be normal and the JFrame responsive until after step 3 is completed. In the outlined solution I don't think steps 4-6 have any such dependency on step 3.
Sorry for my convoluted explanation of what I'm trying to achieve. Have I misunderstood your solution? I would appreciate your comments.
Thanks,
George
[ December 19, 2003: Message edited by: George Marinkovich ]
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34


1. My event handler makes the glass pane visible to keep the JFrame from responding to any events.
2. My event handler sets the busy cursor.
3. My event handler spawns a new thread which among other things calls wait().
4. My event handler calls SwingUtilities.invokeLater(resetMethod)
5. resetMethod makes the glass pane invisible to allow the JFrame to respond to events again, and
6. resetMethod sets the normal cursor.

Your understanding is perfect except for step 4. The event handler doesn't call invokeLater(resetMethod); it's the thread which calls wait() that makes this call, after wait() returns. The event handler returns as soon as it spawns that other thread -- that's the whole point of this exercise, is to have the event handler return quickly so the event-handling thread is then available to repaint the JFrame as soon as the JDialog is closed (the original problem, right?)
George Marinkovich
Ranch Hand

Joined: Apr 15, 2003
Posts: 619
Yes it was my mistake, I had the event thread calling the invokeLater(). The solution makes sense to me now, thank you very much for your response.
But,

doesn't seem to be catching events that occur in mainWindow (a JFrame). So, while the cursor is set to busy as expected and

returns true as expected, I am still able to activate everything on the mainWindow. The glass pane doens't seem to be preventing this. Any ideas?
I've taken a look at GlassPaneDemo in the Swing tutorial, but it's doing a lot more than I want to do with the glass pane (capturing a selected event and painting on the glass pane for instance) and I wasn't able to see what I'm doing wrong by looking at that code.
Any help will be greatly appreciated,
George
[ December 19, 2003: Message edited by: George Marinkovich ]
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

SOrry, yes, it's been a while since I've set this up. While you're initializing the JFrame, add some listeners to its GlassPane which ignore the events your application uses -- i.e., something like

Then when the GlassPane is visible, it will swallow those events and your JFrame won't respond to them.
George Marinkovich
Ranch Hand

Joined: Apr 15, 2003
Posts: 619
That was it. It now works exactly as I hoped it would.
Thank you very much for sharing your expertise. I think I've learned how to handle the event thread correctly (at least in the simple case) and use the glass pane technique to suppress user interaction. Thanks also for your quick responses to all my questions. I feel very lucky to have javaranch and people like you around.
This was the last major problem I was having with the SCJD Exam, so I'll be submitting it soon.
Wishing you a Merry Christmas and a very Happy New Year,
George
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: JFrame not repainting when overlayed JDialog is closed