Get your CodeRanch badge!*
The moose likes Swing / AWT / SWT and the fly likes getting KeyPressed for JDialog? example? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "getting KeyPressed for JDialog? example?" Watch "getting KeyPressed for JDialog? example?" New topic
Author

getting KeyPressed for JDialog? example?

Dave Smith
Greenhorn

Joined: Jan 12, 2000
Posts: 23
Hi,
I am wanting to be able to show a JDialog containing several text fields, and allow the user to close the box by pressing Escape. I imagine this is possible, what do I need to do to pass the keycode to my code. I am aware of the code needed to close the window, and have tried to capture keypresses by implementing a JDialog with the KeyListener interface. However, it didn't appear to be able to recognize any key presses.
Can someone show me an example of extending a JDialog that works?
Thanks.
Ashish Mahajan
Ranch Hand

Joined: Feb 19, 2003
Posts: 77
Hi Dave,
Just write a subclass of JDialog say XDialog and in it's init method write the foll code. And needless 2 say all the dialogs in the project will use this one :-
// The following few lines are used to register esc to close the dialog
Action cancelKeyAction = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
XDialog.this.dispose();
}
};
KeyStroke cancelKeyStroke = KeyStroke.getKeyStroke((char)KeyEvent.VK_ESCAPE);
InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getRootPane().getActionMap();
if(inputMap != null && actionMap != null){
inputMap.put(cancelKeyStroke, "cancel");
actionMap.put("cancel", cancelKeyAction);
}

This will work in most cases but if the dialog contains text component then pressing ESC won't dispose dialog cause the key event is not delivered to Dialog but to the text component. For that what we do :- We have written a general WindowDisposer class that has the responsibility of disposing the dialogs. Instead of clutterring the codes with the window disposing code we have given this responsibility to this class. so any window just needs to call
addwindowListener(new WindowDispose(this));
Now same class can implement KeyListener and in the key pressed can check for the Esc and then can dispose. What we do id to add this class as key listener to every text component we create.
Of these two sol. the former is a standard one. If anyone wanna give better sol than the latter one then it will be very helpful.
Sincerely,
Ashish


The best teams have no specialists, only general contributors with special skills
Ashish Mahajan
Ranch Hand

Joined: Feb 19, 2003
Posts: 77
Hi All,
Please ignore above ugly solution suggested by me few days back.
I was figuring out a proper, standard solution to this common required functionality - disposing the dialog with "ESC".
The requirement was :- All the dialogs should be able to dispose with the "ESC" key pressed. There should not be a need to add key listener to every text component for disposing the dialog.
While doing this i found one missing functionality in text components. If there is any selection is text component and "ESC" is pressed then it should remove this selection. Since every dialog should be disposed at "ESC" even if the text component inside it has focus, then i added one more extended requirement :- If the text component is in dialog then that dialog should be disposed and if that text component is in frame then it should remove selection if there is any when "ESC" is pressed. (naturally we don;t want frame to be disposed at "ESC"). I got a green signal when i found that popular text editors like "TextPad" behaves in the same way.
So here is the revised code of XDialog :-
public class XDialog extends JDialog
{
/////////////
// All the constructors go here
// and all the constructors after calling super's version calls initXDialog method
/////////////
// -- static block
{
// Add Escape key binding to the shared JTextComponent key bindings so that if any
// text component is inside Dialog then dispose that dialog
KeyStroke cancelKeyStroke = KeyStroke.getKeyStroke((char)KeyEvent.VK_ESCAPE);
Keymap map = JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP);
map.addActionForKeyStroke(cancelKeyStroke, cancelKeyAction);
}
private static Action cancelKeyAction = new AbstractAction()
{
public void actionPerformed(ActionEvent ae)
{
Component comp = (Component) ae.getSource();
Window window = SwingUtilities.windowForComponent(comp);
if(window instanceof Dialog){
window.dispose();
}
else if(comp instanceof JTextComponent && ! (comp instanceof JFormattedTextField)){
JTextComponent tc = (JTextComponent) comp;
int end = tc.getSelectionEnd();
if(tc.getSelectionStart() != end){
tc.setCaretPosition(end);
}
}
}
};
/**
* Method for initialization.
* This implementation adds a window listener to dispose itself while closing
* This also adds functionality of disposing if "ESCAPE" is pressed
*/
private void initXDialog()
{
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
KeyStroke cancelKeyStroke = KeyStroke.getKeyStroke((char)KeyEvent.VK_ESCAPE);
InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getRootPane().getActionMap();
if(inputMap != null && actionMap != null){
inputMap.put(cancelKeyStroke, "cancel");
actionMap.put("cancel", cancelKeyAction);
}
}
} // end of class XDialog

But one more thing i observed that Formatted text field should be behaved in a different way in that when "ESC" is pressed in formatted text field it's valid value should be set and that means even if formatted text field is in dialog that dialog should not be disposed. Since the solution involves modifying a shared (static) key map of JTextComponent that means for every JFormattedTextField we create we should override the parent key map to provide a default "ESC" functionality. So it's better to subclass JFormattedTextField say XFormattedTextField which has foll code in it's init :-
KeyStroke cancelKeyStroke = KeyStroke.getKeyStroke((char)KeyEvent.VK_ESCAPE);
JTextComponent.KeyBinding[] bindings = new JTextComponent.KeyBinding[]{ new JTextComponent.KeyBinding(cancelKeyStroke, "reset-field-edit") };
JTextComponent.loadKeymap(getKeymap(), bindings, getActions());

NOTE that the individual requirement can vary.
Hope this helps.
Ashish Mahajan
Ranch Hand

Joined: Feb 19, 2003
Posts: 77
Hi All,
One more thing to note is that the text component's "key binding" is LookAndFeel dependent. but while designing i have assumed that disposing when "ESC" is pressed is desired in all LAFs.
If anybody wanna give different "ESC" actions for different LAFs then one should write a code to listen to "lookAndFeel" property from UIManager in static block and add/remove keystrokes from the shared text component's key map. Like addActionKeyStroke(KeyStroke, Action) method, the interface Keymap also has removeKeyStrokeBinding(KeyStroke) method
Avi Abrami
Ranch Hand

Joined: Oct 11, 2000
Posts: 1121

Hi Dave,
[Wonder why no-one has hassled you about you (unacceptable) handle?]
Have you read this article?
http://www.javaworld.com/javaworld/javatips/jw-javatip72.html
Does it not help you?
Good Luck,
Avi.
Ashish Mahajan
Ranch Hand

Joined: Feb 19, 2003
Posts: 77
Hi Avi,
Thanx for the link. But i'll still go for XDialog than the example in the article the reasons being :-
1. If any text component is placed in the example dialog (and it has focus) then it won't dispose cause the key stroke won't travel up the container hierarchy to reach JRootPane but will be handled by the text component.
2. XDialog adds another functionality of removing selection in the text component if that text component is in frame.
3. The example uses although not deprecated but obselete API namely registerKeyboardAction(ActionListener, KeyStroke, condition). I think the article is written prior to JDK 1.3. In JDK 1.3 Sun guys have introduced an excellent architechture for handling keystrokes. namely getInputMap() and getActionMap(). The obsolete registerKeyboardAction() method hardcodes the key strokes. Since keystrokes/key bindings r LookAndFeel dependent, one should not use that method rather use combination of getInputMap() and getActionMap() which provides a loose coupling between keystrokes and the target action. In short the LookAndFeel should define the inputmap with key as keystroke and a command as value and that command will be used as a key to look up for the action in the action map.
However NOTE that the XDialog still hardcodes the key stroke (ESC) bacause the functionality desired by "ESC" key pressed is same for all the LookAndFeels i.e. disposing the dialog.
So to practice better API, and the reasons stated above i'll still go for XDialog.
Sincerely,
Ashish
Avi Abrami
Ranch Hand

Joined: Oct 11, 2000
Posts: 1121

Gee Ashish, I thought I was showing that link to Dave (not you) -- but thanks, anyway (I guess?)
Avi.
Dave Smith
Greenhorn

Joined: Jan 12, 2000
Posts: 23
Thanks very much for both of your responses. There's no need to fight though
Ashish Mahajan
Ranch Hand

Joined: Feb 19, 2003
Posts: 77
Hi Dave and Avi,
There's no need to fight though

Just wanna say that nobody here is fighting. I have seen the guys here r really and helping. The problem is the channel thru which we r trying to communicate. Here we can't see each other's faces, expressions, mood etc.. Had Avi and I been sitting together I would not even had 2 sign off as Sincerely. However this is still the best (cause it's the cheapest available) medium.
Best Wishes,
Ashish
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: getting KeyPressed for JDialog? example?
 
Similar Threads
TabbedPanere opening major problem
Closing dialog box using windows listener
Thread got stuck?
JDialog --PLS HELP !!
partial display of JOptionPane