Question

JTable's default behavior is changing focus to next cell and I want to force it to move focus to next component (e.g. JTextField) on TAB key pressed.
I overrided isCellEditable method of DefaultTableModel to always return false:

public boolean isCellEditable(int rowIndex, int columnIndex) {
    return false;
}

But it still doesn't change focus to next component!
How should I make JTable change focus to next component instead of next cell?

Was it helpful?

Solution

If you really want this, you need to change the default behavior of the tables action map.

ActionMap am = table.getActionMap();
am.put("selectPreviousColumnCell", new PreviousFocusHandler());    
am.put("selectNextColumnCell", new NextFocusHandler());    

Then you need a couple of actions to handle the traversal

public class PreviousFocusHandler extends AbstractAction {
    public void actionPerformed(ActionEvent evt) {
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        manager.focusPreviousComponent();
    }
}

public class NextFocusHandler extends AbstractAction {
    public void actionPerformed(ActionEvent evt) {
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        manager.focusNextComponent();
    }
}

Another approach would be to disable the underlying Action...

ActionMap am = table.getActionMap();
am.get("selectPreviousColumnCell").setEnabled(false);
am.get("selectNextColumnCell").setEnabled(false);

(haven't tested this)

The benefit of this approach is can enable/disable the behaviour as you need it without needing to maintain a reference to the old Actions

OTHER TIPS

The shift-/tab keys are used by default for transfering focus between components. JTable explicitly requests to handle the shift-/tab internally (by providing sets of focusTraversalKeys which doesn't include those).

Following the general rule (if there's specilized api available for a task, use that instead of rolling your own), the solution is to set traversal keys to again contain them:

Set<AWTKeyStroke> forward = new HashSet<AWTKeyStroke>(
        table.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
forward.add(KeyStroke.getKeyStroke("TAB"));
table.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, forward);
Set<AWTKeyStroke> backward = new HashSet<AWTKeyStroke>(
        table.getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS));
backward.add(KeyStroke.getKeyStroke("shift TAB"));
table.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, backward);

To reset to the standard keyboard bindings (typically TAB and SHIFT+TAB), simply specify null for the keystrokes parameter to Component.setFocusTraversalKeys:

table.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null);
table.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top