Search code examples
javaswingjtextfieldkey-bindingskeyevent

Override VK_Tab Focus action


Good Day!

I am tying to add keyevent listener to jTextField so that if the user pressed the tab key, the caret position will go to the end of the text inside the jtextField, here is my code:

private void jTextField1KeyPressed(java.awt.event.KeyEvent evt) {
    if(evt.getKeyCode()==KeyEvent.VK_TAB){
        evt.consume();
        jTextField1.setCaretPosition(jTextField1.getText().length());
    }
}

But it doesn't work.

How can i make this happen?


Solution

  • One way is to:

    • First of all, don't use a KeyListener since this is a Swing application, and you shouldn't use KeyListeners in Swing apps if it can be avoided.
    • Next set the focus traversal keys enabled property of your JTextField to false via jTextField1.setFocusTraversalKeysEnabled(false);
    • Then use key bindings, (again) not a KeyListener, to change the behavior of the tab key for that component.

    For example:

    import java.awt.event.*;
    import javax.swing.*;
    
    public class OverrideTab {
       private static void createAndShowGui() {
          JPanel mainPanel = new JPanel();
          final JTextField jTextField1 = new JTextField("This is the text", 20);
    
          mainPanel.add(new JButton("Here just to get focus"));
          mainPanel.add(jTextField1);
    
          // just to move the caret to position 0 so we can see the key
          // bindings code in action          
          jTextField1.addFocusListener(new FocusAdapter() {
             @Override
             public void focusGained(FocusEvent e) {
                jTextField1.setCaretPosition(0);
             }
          });
    
          // turn tab key as focus traversal off for the component
          jTextField1.setFocusTraversalKeysEnabled(false);
    
          // set the key bindings
          int condition = JComponent.WHEN_FOCUSED;
          InputMap inputMap = jTextField1.getInputMap(condition);
          ActionMap actionMap = jTextField1.getActionMap();
          String tab = "tab";
          inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), tab);
          actionMap.put(tab, new AbstractAction() {
    
             @Override
             public void actionPerformed(ActionEvent arg0) {
                jTextField1.setCaretPosition(jTextField1.getText().length());
                System.out.println("here");
             }
          });
    
    
    
          JFrame frame = new JFrame("OverrideTab");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.getContentPane().add(mainPanel);
          frame.pack();
          frame.setLocationByPlatform(true);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }
    

    Of course this code will prevent you from being able to shift-tab out of the JTextField, and so if this behavior is necessary and important, you could use setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.<KeyStroke>emptySet()) instead of completely disabling focus traversal.

    Also, your desired behavior goes against the standards of most windowing operating systems, so you'll want to have a darn good reason for desiring this because you may confuse your users.