Search |
||
Dialog DiatribePosted by hansmuller on October 27, 2006 at 5:48 PM PDT
I've been writing the occasional small application recently and now and then I blunder into a problem with Java SE that's, uh..., well, annoying. I realize that I'm not the only one who's had this experience and I'm probably not the only one who seeks relief by writing a lengthy diatribe and then sending it to whomever might be guilty of creating the situation. Of course, in my case that's often me, and since relief usually doesn't come from berating oneself, I'm guilty of sending the occasional long crabby missive to the people who are currently responsible for maintaining things that I'm probably responsible for bollocksing up in the first place. It's not a particularly endearing habit. I sent the following to Swing's technical lead, Shannon Hickey, and he confirmed that the details, though twisted with bile, are essentially correct. So in the interest of furthering my own therapy, and also to ensure that some record of this will be stored away in Google's indices till the end of time, I thought I'd share. I would think that a fairly common idiom in a Swing application would be to popup a dialog in response to selecting a menu item. Given Matisse, we'll assume that the JDialog has been created with the IDE, rather than some JOptionPane convenience method, and given rudimentary aesthetics, assume the dialog should be centered over the menu item's frame. Accomplishing this seems to be much too difficult:
public void showMyDialog(ActionEvent e) {
// How to find the Dialog's Frame owner?
Window dialogOwner = null;
JDialog dialog = new MyDialog(dialogOwner, true); // true => modal Dialog
dialog.pack();
// How to center the Dialog?
dailog.setVisible(true);
}
The first problem to deal with is mapping from the menu item's ActionEvent to the frame that contains the menu item. The frame will be the dialog's owner as well as the component we're going to center the dialog relative to. There seems to be an overabundance of SwingUtilities methods that address this trivial problem:
To find the Frame that owns a JMenuItem, we have to follow the JPopupMenu's "invoker" property, which gets us back into the component hierarchy. So to find the frame that corresponds to an ActionEvent one must write (!):
Frame frameForActionEvent(ActionEvent e) {
if (e.getSource() instanceof Component) {
Component c = (Component)e.getSource();
while(c != null) {
if (c instanceof Frame) {
return (Frame)c;
}
c = (c instanceof JPopupMenu) ? ((JPopupMenu)c).getInvoker() : c.getParent();
}
}
return null;
}
It would more useful to have written
But we're still not done, because we must also center the dialog over the frame. Naturally there are other useful positions for the dialog. Centering a dialog over its frame happens to be what started me on this quest. I have it on good authority that Windows.setLocationRelativeTo() is the handy method for this job. The javadoc for this method isn't promising:
OK so far. Except it sounds like I'm going to have to compute the relative origin of my dialog and deal with edge (of the screen) conditions. Yech.
Huh? What does "the component" refer to in this sentence? I
assume they're not referring to this Window and I have to
wonder what "showing" means in this context. Is is the same
thing as
This, no doubt, means that the method will endeavor to find a location for my dialog that respects the relative location I've specified, without making part of the dialog appear off-screen. Good, I think. So I still appear to be stuck with computing an origin for my dialog that centers it relative to its owner. Before I code that, I try leaving the origin of the new dialog at 0,0, which is the default:
public void showMyDialog(ActionEvent e) {
Window dialogOwner = frameForActionEvent(e);
JDialog dialog = new MyDialog(dialogOwner, true);
dialog.pack();
aboutBox.setLocationRelativeTo(dialogOwner);
dialog.setVisible(true);
}
Miraculously, this works. The dialog appears centered over the dialogOwner unless that would cause the dialog to appear off-screen. I have no idea why it works, since according to the "spec" (and the name of the method) I should have had to compute an appropriate relative origin for the dialog. But I guess I don't. Frankly, I think this whole mess is a mini-travesty. If I'm going to show a dialog, I should be able to do so without writing code that digs around the component hierarchy and without experimentally determining what something as simple (and not terribly useful) as Window.setLocationRelativeTo() does. There, that feels a little better. A seven year old bug that covers the menu item to frame lookup problem is still open. Given the fact that it's accumulated exactly 0 votes in that time, perhaps no one has ever cared about the problem quite as much as I do at this moment. I would think that a cleaner way to handle this case would be some static methods that handled the entire idiom, for example:
public void showMyDialog(AWTEvent event) {
Window dialogOwner = Window.eventToWindow(event);
JDialog dialog = new MyDialog(dialogOwner, true);
Window.showModalDialog(dialog); // Center dialog relative to its owner
}
And Shannon suggested that the method name might be rationalized
as implying that the Window is be moved to a location that makes
its relationship to the component parameter obvious.
Typically that means centering the Window relative to the
component. In return for that tortured explanation, I had to
agree to file an RFE about the
Thanks for listening. »
Related Topics >>
Java Desktop Comments
Comments are listed in date ascending order (oldest first)
|
||
|
|