JTextArea Cell Editor TAB Key Traversal To Next Cell In JTable


By default, pressing the TAB key in a JTextArea will insert a tab character instead of transferring focus to the next focusable component. But if your JTextArea is a cell editor within a JTable, and you want the TAB key to transfer to the next cell on an on, what I did was add a KeyListener to the JTextArea and capture the TAB key event when pressed, then calling the JTable changeSelection() method to transfer focus to the next cell.

If the focus was on the last column of a row, it will check if there is another row next to it. If there is, focus will be transferred to the next row on the first column and so on and so forth. Here is the source code for my TextAreaCellEditor class.

If you want the TextAreaCellEditor class to implement trapping the TAB key event, just supply a boolean parameter true to the constructor.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
public class TextAreaCellEditor extends AbstractCellEditor implements TableCellEditor, KeyListener {
    private JTextArea textArea;
    private JScrollPane scrollPane;
    private JTable table;
    private boolean disableTabKey;
 
    public TextAreaCellEditor() {
        init();
    }
 
    public TextAreaCellEditor(boolean disableTabKey) {
        this.disableTabKey = disableTabKey;
        init();
    }
 
    private void init() {
        textArea = new JTextArea();
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        textArea.setRows(3);
        scrollPane = new JScrollPane(textArea);
        scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        scrollPane.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent fe) {
                textArea.requestFocusInWindow();
                textArea.selectAll();
            }
        });
        if (disableTabKey) textArea.addKeyListener(this);
    }
 
    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        textArea.setText(value.toString());
        if (this.table == null) this.table = table;
        table.setRowHeight(textArea.getRows() * 20);
        return scrollPane;
    }
 
    @Override
    public Object getCellEditorValue() { return textArea.getText(); }
 
    @Override
    public void keyTyped(KeyEvent e) { }
 
    @Override
    public void keyPressed(KeyEvent ke) {
        System.out.println(table.getEditingRow() +","+table.getEditingColumn());
        // tab key will transfer focus to next cell
        if (disableTabKey && ke.getKeyCode() == KeyEvent.VK_TAB && !ke.isShiftDown()) {
            ke.consume();
 
            int column = table.getEditingColumn();
            int row = table.getEditingRow();
            if ((column + 1)  >= table.getColumnCount()) {
                // if column is last column, check if there is next row
                if ((row + 1) >= table.getRowCount()) row = -1;
                else {
                    row++;
                    column = 0;
                }
 
            } else column++;
 
            if (row > -1 && column > -1)
                table.changeSelection(row, column, false, false);
 
            return;
        }
    }
 
    @Override
    public void keyReleased(KeyEvent e) { }
}

Found this post useful? Buy me a cup of coffee or help support the sponsors on the right.

Related Posts with Thumbnails