Using the help given in a tech tip, I developed a blocker event queue that allows me to create partially modal dialogs. These dialogs are non-modal as far as JAVA is concerned, and modal only with respect to its ancestors. Therefore, if there are any other frames in my application that are not ancestors of a dialog, I can continue any kind of activity in these frames.
But in implementing this solution, I have run into a problem. For non-modal dialogs, JAVA does not block in show(). So show() returns instantly. In my application, I wrap show inside another function that tracks what button was pressed to dispose the dialog, and my application uses this return value for further processing. But since show() doesn't block, the return value has no relation to the button used to dispose the window.
example:
protectedint displayDialog()
{
show();
return iButtonPressed;
}
// onOK() is action handler for OK button in the dialog
publicvoid onOK()
{
iButtonPressed = OPT_OK;
dispose();
}
// onCancel is action handler for Cancel button in the dialog
publicvoid onCancel()
{
iButtonPressed = OPT_CANCEL;
dispose();
}
// elsewhere
privatevoid someFunction()
{
int iRet = someDialog.display();
if(iRet == OPT_OK)
{
doSomething();
}
else
{
doSomethingElse();
}
}
But since display is returning immediately, the actual return value is some random value (probably last set value).
Hence my question:
Can I make show() block, while maintaining my partial modality?? Any help SERIOUSLY appreciated...
I think there are two approaches. First, forget the serial code path idea just because its a dialog and have the onOK and onCancel functions call doSomething and doSomethingElse (this is what I do).
Or, if you want, take a look at the implementation of Dialog.show() where the code is to pump events from where you are, rather than returning to the AWT event pump. Looks a bit hairy but, if you have overridden and Dialog.isModal() it looks as though Dialog.show wouldn't return for your "modal" dialogs anyway?
Re: show not blocking for partially modal classes
Feb 6, 2004 2:03 AM
(reply 2
of 18) (In reply to
#1 )
Hi Tom,
Thanks for your help yet again!!!
I should have been more clear, but the doSomething() and doSomethingElse() functions are in another class, and based on the class that calls the dialog, the implementation of these functions may vary. For example, if my dialog selects 3 out of 5 names, one class uses these names to send an email to them, the other class simply prints the selected names. Hence, I need the other classes to know which dialog was displayed, and onOK() of each dialog, take a different action. Hence the need for these functions separately... But I guess I could use your solution in one long-winded way; I could call callingComp.doSomething() or callingComp.doSomethingElse(), and define separate doSomething() functions for each dialog that component plans to display!!!!
I did try overriding isModal() for the dialog. Either its a problem with my code (and I seriously need to try out yours), or the whole thing's wrong, but using isModal() to return true causes the frame that called the dialog to always stay blocked (even after dispose), and the partial modality isn't obtained, as the other frame stays blocked while the dialog displayed. Hence show() does block, but this isn't all I wanted...
Re: show not blocking for partially modal classes
Feb 6, 2004 2:27 AM
(reply 3
of 18) (In reply to
#2 )
OK well I didn't seriously expect isModal to work. I looked at my code and I don't do that. Of course it will negate the solution - silly me!
Anyway, as for the callback solution, why not include an interface on the classes that you want your dialog to call back and pass the object to your extended dialog as you show it so:
Re: show not blocking for partially modal classes
Feb 6, 2004 3:43 AM
(reply 4
of 18) (In reply to
#3 )
Hi Tom,
Seriously, thanks for all the time and effort!!!
Now, about the callback, well I had already thought of a similar concept, only instead of an interface, it was a protected function in the base class of the calling component class. The only problem there was sending a reference to the calling object in the constructor of the dialog, and modifying all my dialogs and calling components.
Therefore, this is an option I shall definitely consider, but preferably as a last resort!!!!
Re: show not blocking for partially modal classes
Feb 6, 2004 4:01 AM
(reply 5
of 18) (In reply to
#4 )
I don't know how big your code base is but using an interface has the advantage of not tying the dialogs (all of which you have to extend anyway because of the modal implemetation details) to the calling components. If you use a protected method then this will happen and I forsee grief.
You don't even need to modify the calling components to implement the interface, just use an anonymous inner class where you are already calling show and have all your dialog extensions accept the argument. Am I clear?
Re: show not blocking for partially modal classes
Feb 6, 2004 4:24 AM
(reply 6
of 18) (In reply to
#5 )
Hi Tom,
I understand about not tying the dialogs to the calling components, but all dialogs in my application are called by at most three types of calling classes. But I understand your point, that irrespective of the class that calls the dialog, I handle only the interface type in my dialog, and that saves me major grief later on.
And to note, I already have over 100 classes that call my dialog, so 100 classes to implement interface, and over 50 dialogs, so 50 classes to use this interface... so its a major change.
And as for the semi-modal behaviour, just adding the Blocker.java class and overriding the show(), hide()and dispose() functions in my dialog's base class gave me the required behaviour, needing no further changes to the dialogs themselves.
I am lost about the suggestion to avoid changing all calling components... Could you elaborate??? Assume my current calls are as follows:
// the calling component; its usually a JPanel derivative
publicvoid onSomeEvent()
{
MyDialog myDialog = new MyDialog();
if(myDialog.display() == MyDialog.OPT_OK)
{
doSomething();
return;
}
doSomethingElse();
}
// the MyDialog class...
publicint display()
{
// some pre-show processing
show();
return iEndState;
}
protectedvoid onOK()
{
iEndState = OPT_OK;
dispose();
}
protectedvoid onCancel()
{
iEndState = OPT_CANCEL;
dispose();
}
I know I just repeated some of the code from above, but hope I made things clearer... Now where in this code would I add the inner anonymous class??? And I would HAVE to write the onOK() and onCancel() functions in all calling component classes, right??
Re: show not blocking for partially modal classes
Feb 6, 2004 5:15 AM
(reply 7
of 18) (In reply to
#6 )
No problem - everything is clear.
So to summarise:
1) You like the partial modality you've implemented and the benefits it brings - so the GUI is OK!
2) You have a large code base but luck was on your side because you have your own dialog base class, so implementing the partial modality stuff was easy. Your buy-in so far is cheap.
3) Sadly, your flow for the formerly modal dialogs took advantage of the native Java blocking Dialog.show().
Because your dialogs are now not Java modal, its not blocking any more.
I reckon its a non-starter to try to make show blocking, so you have to decide to bite the bullet or back out. This will mean moving some code around and, yes, it means modifying the 100 or so places that call the dialogs. I think you already understand the implications but if you have the base class for your dialogs
then may be its a bit easier by putting the callback code there.
// the calling component; its usually a JPanel derivative
publicvoid onSomeEvent()
{
MyDialog myDialog = new MyDialog();
myDialog.display(new DialogCallback()
{
publicvoid onOK() { doSomething(); }
publicvoid onCancel() { doSomething(); }
});
}
// the MyDialog class...
publicint display(DialogCallback dcb)
{ // some pre-show processing
// remember callback object - the modality means we don't reenter here.
dcb_ = dcb;
show();
}
protectedvoid onOK()
{
dcb_.onOK();
dispose();
}
protectedvoid onCancel()
{
dcb_.onCancel();
dispose();
}
Don't think there's another way if you want to carry on.
Re: show not blocking for partially modal classes
Feb 8, 2004 8:20 PM
(reply 8
of 18) (In reply to
#7 )
Hi Tom,
Thanks again... Now I get the use of the anonymous class... But if I have to change the call to the dialog anyways, I have to change the calling class too, and might as well add the interface directly to the calling class.
So we don't seem to see any way to make show() blocking while dialog is non-modal... Pity. That would have been SO much better.
Great, this looks like the way to go, long or not!
Re: show not blocking for partially modal classes
Feb 9, 2004 1:22 AM
(reply 10
of 18) (In reply to
#9 )
Hi,
Ignore the JavaHelpIssue, I found the solution! This is a known problem due to Bug # 4667544. It has to do with us adding a new event queue, but the getSystemEventQueue() function of the Toolkit class returning the default event queue always. This has been fixed in the new version of Java'2 SDK, 1.4.2_03.
Re: show not blocking for partially modal classes
Mar 7, 2004 8:03 PM
(reply 12
of 18) (In reply to
#11 )
Hi JJasper,
Thanks for the reply! I haven't had a chance yet to see the source code, but I did run the demo... The description of the project DOES seem to be what I want...
However, did u notice the severe flicker when I open the modal windows? or even 2 modal windows? And I am unable to move the windows around, was this intentional? And the text next to the button says that the window will be opened in the center of the frame, but that doesn't happen!
I'm sure these questions can be answered by looking at the code, but if you could give them to me, I'd appreciate it. For now, I am allowing my functions to return after the show, and using call-back functions to do the post-show processing required. So I have removed the dependecy of my code on blocking show.
1) And I am unable to move the windows around, was this intentional?
2) And the text next to the button says that the window will be opened in the center of the frame, but that doesn't happen!
Problem 1 2 occur because of a test that was left behind in the code. See source of TestModalFrame and method:
private Window createNormalWindow(Component cmp)
{
// final JModalWindow jmw = new JModalWindow(SwingUtilities.windowForComponent(cmp), cmp, false);
final JWindow jmw = new JWindow(SwingUtilities.windowForComponent(cmp));
...
if (jmw instanceof JModalWindow)
{
((JModalWindow)jmw).centerOfOwner();
}
}
(1) JWindow can't be moved. Dragging is added to JModalWindow.
Note: MOVE_CURSOR only shows a the border of the window (1 pixel wide).
(2) JWindow isn't centered because it doesn't have the conveniens method centerOfOwner().
Code is update and reposted at the site (didn't update the version number).
3) However, did u notice the severe flicker when I open the modal windows? or even 2 modal windows?
When does the flickering happen: in the parent frame and only the first time when a modal window is opened ? This occurs when resizing is disable.
Temporary solution: Just remove setResizable() from setBusy method in JModalFrame. I look for a different solution to block resizing of the frame or remove this functionality altogether.
4) I noticed also a problem myself when the frame is deiconified after iconifying it, when it is still blocked. But this functionality already needed a better implementation.
Summary:
problem 1 / 2 solved in update version v0102.
problem 3 has workaround
For problem 3 4 I will create an issue and try to solve them in version v0103.
Thanks for spotting problems 1 2.
I will create another reply here when problems 3 4 are solved or disabled.
Thanks for the prompt reply... Noted your replies. As soon as my current schedule is met, and I have some free time, I shall take a good look at the code you have written.
Good work!
Shefali.
This topic has
18
replies
on
2
pages.
1
|
2
|
Next »