tags:

views:

711

answers:

2

Hi All

I have a panel containing a number of components, one of which is a JTable. When the JTable has focus and the TAB key is pressed, the default behaviour is to move focus from cell to cell within the table. I need to change this to focus on the next component instead i.e. leave the JTable completely.

Ctrl-TAB achieves the desired results, but is not acceptable to the user. I can add a key listener to the table and change the focus when TAB is pressed, but it feels as though there might be a better way to do this.

Any ideas?

Thanks...

+3  A: 

You would typically do this by adding an Action to the components action map and then binding a keystroke with it in the component's input map (example code below). However, this will not work for tab as this event is consumed by the focus subsystem unless you add the following line to remove tab as a focus traversal key:

tp.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.<AWTKeyStroke>emptySet());

Here's the full example code:

public static void main(String[] args) {
    final JTabbedPane tp = new JTabbedPane();

    // Remove Tab as the focus traversal key - Could always add another key stroke here instead.
    tp.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.<AWTKeyStroke>emptySet());

    KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);

    Action nextTab = new AbstractAction("NextTab") {
     public void actionPerformed(ActionEvent evt) {
         int i = tp.getSelectedIndex();
         tp.setSelectedIndex(i == tp.getTabCount() - 1 ? 0 : i + 1);
     }
    };

    // Register action.
    tp.getActionMap().put("NextTab", nextTab);
    tp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, "NextTab");

    tp.addTab("Foo", new JPanel());
    tp.addTab("Bar", new JPanel());
    tp.addTab("Baz", new JPanel());
    tp.addTab("Qux", new JPanel());

    JFrame frm = new JFrame();

    frm.setLayout(new BorderLayout());
    frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frm.add(new JButton(nextTab), BorderLayout.NORTH);
    frm.add(tp, BorderLayout.CENTER);
    frm.setBounds(50,50,400,300);
    frm.setVisible(true);
}
Adamski
That was the tip I needed. Couldn't figure out why TAB was not working, but had an idea it was because of the FocusPolicy.
Tony Eichelberger
A: 

Well you probably don't want to just get rid of the Tab Action because it has other responsibilities. For example, when you are editing a cell the Tab Action stops cell editing before moving to the next cell. So you probably want to retain this behaviour while adding extra behavour to change focus to the next component.

I refer to this as "wrapping an action" and you can find an example of this by checking out the Table Tabbing action. You should be able to easily customize the code to use the KeyboardFocusManager to transfer focus.

camickr