This post originated from an RSS feed registered with Java Buzz
by Danno Ferrin.
Original Post: Extending Swing via Listeners
Feed Title: And They Shall Know Me By My Speling Errors
Feed URL: http://shemnon.com/speling/archives/cat_GUI.rdf
Feed Description: Danno Ferrin's Many Reasons he was a Comp Sci Major and not an English Major
With a framework as nimble as Swing there are many ways to skin a cat. This is possibly one of the sources of many complains about Swing. For example Sam Dalton wrote a class that implements a dialog that closes when the escape key is pressed. Subclassing JDialog is certainly one way t do it, but I probably would have simply wrote a utility method...
A couple of changes reflect my swing codeing preferences. First, I call dispose() instead of hide(). My reasons are twofold: first until a window is disposed it takes up native graphics resources, and can essentially be a big memory leak until the object becomes inaccessible and is finalized. The second reason has to do with a clean JVM exit. While any AWT resources are realized (i.e. have native OS resources allocated) the AWT event thread will keep running and the JVM will not exit. If all of the windows are disposed() then the AWT event thread will enter a state that will allow the JVM to terminate. No more calls to System.exit(0).
The second thing I changed was which action map I put the escape key in. Sam used WHEN_FOCUSED which is fine if there are no focusable components in the dialog. But throw in a button or text field and the action may never get fired. There are actually two options here, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT and WHEN_IN_FOCUSED_WINDOW. I chose the latter because this is also how the JMenuItems register their accelerator keys and the desired operation is essentially the same. Since we are adding the action to the JRootPane there are no differences between the two.
By using a utility method we can also add this behavior to any free standing component. One of the issues Swing has to deal with is that higher up in the AWT hierarchy dialogs and frames were separated. To deal with this they created an interface javax.swing.RootPaneContainer so that they can treat all root level components the same. Hence this behavior can be added to any JFrame, JDialog, JWindow, JApplet, or JInternalFrame.
And please, if you have obnoxious splash screens either have a user preference to turn it off or add this to the JWindow so the user can click it and press escape. Wouldn't that be nice.