Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / GUI / January 2004

Tip: Looking for answers? Try searching our database.

JTextField consuming enter and escape

Thread view: 
Jason Siemens - 14 Jan 2004 15:59 GMT
Does anyone know a way to stop a JTextField component from consuming
VK_ENTER and VK_ESCAPE keys?  I need these keys to be picked up by the
parent to drive an OK and Cancel button (it works fine for the other
controls on the same panel).

I have of course tried all of the following (picked up from various
sites, etc. around the web) when the control is created, with no luck:

{
  KeyStroke en = KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0, false );
  KeyStroke esc = KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false );

  unregisterKeyboardAction( en );
  unregisterKeyboardAction( esc );

  getKeymap().removeKeyStrokeBinding( en );
  getKeymap().removeKeyStrokeBinding( esc );

  getInputMap( JComponent.WHEN_FOCUSED ).remove( en );
  getInputMap( JComponent.WHEN_IN_FOCUSED_WINDOW ).remove( en );
  getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ).remove(
en );

  getInputMap( JComponent.WHEN_FOCUSED ).remove( esc );
  getInputMap( JComponent.WHEN_IN_FOCUSED_WINDOW ).remove( esc );
  getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ).remove(
esc );
}

{
  KeyStroke en = KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0, true );
  KeyStroke esc = KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, true );

  unregisterKeyboardAction( en );
  unregisterKeyboardAction( esc );

  getKeymap().removeKeyStrokeBinding( en );
  getKeymap().removeKeyStrokeBinding( esc );

  getInputMap( JComponent.WHEN_FOCUSED ).remove( en );
  getInputMap( JComponent.WHEN_IN_FOCUSED_WINDOW ).remove( en );
  getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ).remove(
en );

  getInputMap( JComponent.WHEN_FOCUSED ).remove( esc );
  getInputMap( JComponent.WHEN_IN_FOCUSED_WINDOW ).remove( esc );
  getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ).remove(
esc );
}

Thanks,

Jason.
Jim Sculley - 14 Jan 2004 17:30 GMT
> Does anyone know a way to stop a JTextField component from consuming
> VK_ENTER and VK_ESCAPE keys?  I need these keys to be picked up by the
[quoted text clipped - 3 lines]
> I have of course tried all of the following (picked up from various
> sites, etc. around the web) when the control is created, with no luck:

You are missing the relationship between action maps and input maps.
The InputMap ties a particular key sequence to an action identifier.
This action identifier is used to look up the appropriate action in the
ActionMap.  Making changes to the InputMap won't affect the ActionMap if
the specified action identifier doesn't exist.  By default, there is no
action assigned to ENTER or ESC in the ActionMap of a JTextField.  As a
result, adding/reassigning items to/in the InputMap for ENTER or ESC
will have no affect on the application.

Here's a small example which prints a message to stdout when the ENTER
or ESC is pressed while in a JTextField:

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.KeyStroke;

public class TFTest {
    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JTextField tf = new JTextField(20);

        InputMap im = tf.getInputMap();
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "enter");
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "escape");
       
        ActionMap am = tf.getActionMap();
        am.put("enter", new AbstractAction() {
                public void actionPerformed(ActionEvent ae) {
                    System.out.println("ENTER pressed");
                }
        });
       
        am.put("escape", new AbstractAction() {
                public void actionPerformed(ActionEvent ae) {
                    System.out.println("ESC pressed");
                }
        });
       
        f.getContentPane().add(tf);
        f.pack();
        f.setVisible(true);
    }
}

Jim S.
Signature

Remove my extraneous mandibular appendages to reply via e-mail

Jason Siemens - 14 Jan 2004 22:26 GMT
Thanks Jim,

You are correct, the action/input maps were not doing anything.  I was
able to capture the Enter and Escape events using your method.  What I
really want to achieve is to have the JTextField control act the same as
any other control such that I can capture the VK_ENTER and VK_ESCAPE on
the root pane on the dialog.

To elaborate, I have subclassed both JTextField and JDialog.  In
JDialog, I have code in the JDialog subclass to click the cancel button
in the dialog whenever Escape is pressed (and the default button when
the Enter is pressed):

getRootPane().registerKeyboardAction(
  new ButtonClickAction( cancelButton ),
  KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0 ),
  JComponent.WHEN_IN_FOCUSED_WINDOW );

This works when any control has the focus, whether it be JPasswordField,
JTextBox, JButton, etc..  Everything except JTextField.

I did try your method of adding an Action to the ActionMap for the
JTextfield.  This would work fine if I could figure out how to send a
KeyEvent directly to the parent without it coming back to the JTextField
(and creating a stack overflow in the process).

Jason.

>> Does anyone know a way to stop a JTextField component from consuming
>> VK_ENTER and VK_ESCAPE keys?  I need these keys to be picked up by the
[quoted text clipped - 56 lines]
>
> Jim S.
Alan Moore - 15 Jan 2004 10:00 GMT
>To elaborate, I have subclassed both JTextField and JDialog.  In
>JDialog, I have code in the JDialog subclass to click the cancel button
[quoted text clipped - 5 lines]
>   KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0 ),
>   JComponent.WHEN_IN_FOCUSED_WINDOW );

You have an action that clicks a button?  That's very, um, creative!

Here's how I do it.  To have the ESC key close the dialog, I use this
method:

 protected void dialogInit()
 {
   super.dialogInit();
   JLayeredPane layeredPane = getLayeredPane();
   closeDialogAction = getCloseDialogAction();
   String actionName = "close-dialog";
   KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
   layeredPane.getActionMap().put(actionName, closeDialogAction);
   layeredPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
       .put(stroke, actionName);
 }

When I create the "Cancel" button, I attach the same action to it:

 cancelButton = new JButton(dialog.getCloseDialogAction());

In my case, the button's label is taken from the action's properties,
but you can also set it yourself:

 cancelButton.setText("Cancel");

As for the ENTER key, all you should have to do is set the
corresponding button as the RootPane:

 dialog.getRootPane().setDefaultButton(okButton);

However, if you add an ActionListener to your JTextField, it will
consume the ENTER key, as that's what triggers the ActionLisetner.
Otherwise, as Jim said, JTextField will ignore the ENTER key.
Jason Siemens - 15 Jan 2004 15:58 GMT
Thanks Alan,

I found out what my problem was...my own stupidity.  Last week, I
changed my subclass of JTextField to inherit from JFormattedTextField
instead and completely forgot I did it.  Of course, this is a completely
different component and this problem is a known bug in 1.4.1 (Bug parade
#4741926).

So, I got around it by adding an action handler (for both Enter and
Escape) to my dialog like this :

JRootPane rootPane = getRootPane(  );
KeyStroke ky = KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0 );
rootPane.getActionMap(  )
        .put( InterfaceConstants.DEFAULT_BUTTON_ACTION_NAME,
              new ButtonClickAction( defaultButton ) );
rootPane.getInputMap( JComponent.WHEN_IN_FOCUSED_WINDOW )
        .put( ky, InterfaceConstants.DEFAULT_BUTTON_ACTION_NAME );

And then adding a KeyListener to the formatted text field that calls the
action attached to the root pane directly:

public void keyPressed( KeyEvent e ) {
  int key = e.getKeyCode(  );

  if ( key == KeyEvent.VK_ESCAPE ) {
    /* call the cancel button action */
    Action cancelAction = getRootPane(  )
                            .getActionMap(  )
                            .get(
InterfaceConstants.CANCEL_BUTTON_ACTION_NAME );

    if ( cancelAction != null ) {
      cancelAction.actionPerformed( null );
    }
  } else if ( key == KeyEvent.VK_ENTER ) {
    /* call the default button action */
    Action defaultAction = getRootPane(  )
                             .getActionMap(  )
                             .get(
InterfaceConstants.DEFAULT_BUTTON_ACTION_NAME );

    if ( defaultAction != null ) {
      defaultAction.actionPerformed( null );
    }
  }
}

Thanks for your help.

>>To elaborate, I have subclassed both JTextField and JDialog.  In
>>JDialog, I have code in the JDialog subclass to click the cancel button
[quoted text clipped - 40 lines]
> consume the ENTER key, as that's what triggers the ActionLisetner.
> Otherwise, as Jim said, JTextField will ignore the ENTER key.


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.