Search code examples
javaswinglistenerjcombobox

Enter Key to behave as Tab on an Editable JComboBox


I have a JComboBox set as Editable which I would like the user to be able to jump to the next control after hitting the enter key. I have tried many approaches but none of them worked, on one of them the event is fired successfully (EditorCompoment.keyRelease) however the method "transferFocus()" does not transfer the focus to the next control like it should. Any help is much appreciated. Thanks

public static void addEnterKeyListener(final javax.swing.JComboBox field)
{
    field.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
    field.setFocusTraversalKeysEnabled(false);

    Action myAction = new AbstractAction() {

    @Override
    public void actionPerformed(ActionEvent e) {

        field.transferFocus();
    }

    };

    field.getActionMap().put("enter-action", myAction);

    field.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("ENTER"), "enter-action");

    field.addKeyListener(new KeyAdapter()
    {
        @Override
        public void keyReleased(final KeyEvent e)
        {
            if (e.getKeyCode() == KeyEvent.VK_ENTER)
            {
                System.out.println("Pressed enter inside JComboBox");
                field.transferFocus();
            }
        }
    });

    field.getEditor().getEditorComponent().addKeyListener(new KeyAdapter()
    {
        @Override
        public void keyReleased(final KeyEvent e)
        {
            System.out.println("Pressed enter inside JComboBox #2");

            if (e.getKeyCode() == KeyEvent.VK_ENTER)
            {                    
                field.transferFocus();
                /*This will fire but will not transfer the focus to the next control*/
                System.out.println("Transfered the focus from JComboBox");
            }
        }
    });

    field.getEditor().addActionListener(new ActionListener() 
    {
        @Override public void actionPerformed(ActionEvent arg0) 
        {
            field.transferFocus();
        }               
    });

    System.out.println("Added enter events to JComboBox");
}

Solution

  • Apply an ActionListener to the editorComponent (a JTextField) of the combo's editor:

    import java.awt.*;
    import java.awt.event.*;
    
    import javax.swing.*;
    
    public class JComboBoxDemo implements Runnable
    {
      public static void main(String[] args)
      {
        SwingUtilities.invokeLater(new JComboBoxDemo());
      }
    
      public void run()
      {    
        JComboBox comboBox = new JComboBox(new String[]{"A", "B", "C"});
        comboBox.setEditable(true);
    
        final JTextField editorComponent = (JTextField) comboBox.getEditor().getEditorComponent();
        editorComponent.addActionListener(new ActionListener()
        {
          @Override
          public void actionPerformed(ActionEvent e)
          {
            editorComponent.transferFocus();
          }
        });
    
        JPanel panel = new JPanel(new FlowLayout());
        panel.add(new JLabel("Field 1"));
        panel.add(comboBox);
        panel.add(new JLabel("Field 2"));
        panel.add(new JTextField(10));
        panel.add(new JLabel("Field 3"));
        panel.add(new JTextField(10));
    
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
    
        Container c = frame.getContentPane();
        c.setLayout(new BorderLayout());
        c.add(panel, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
      }
    }