4

Let me introduce the scenario of my problem. I wish to present the content of a database table in a JTable. With this JTable I should be able to insert new rows, delete rows, and update the content of the fields of the existing rows.

The first desired behavior is that when a cell gets the focus, if it is editable, it enters in edit mode directly with all their content selected if its an alphanumeric content. (Text, numbers, dates, etc.)

The next desired behavior is that the Enter key works as the Tab key, ie, pressing the Enter key focus must be transferred to the next cell (and if this is editable then enter edit mode) both forward (left to right) or backward.

To address the first requirement, I overwrite the changeSelection method of the JTable class with the following method.

@Override
public void changeSelection(int row, int column, boolean toggle, boolean extend) {
    super.changeSelection(row, column, toggle, extend);
    if (editCellAt(row, column)) {
        Component editor = getEditorComponent();
        editor.requestFocusInWindow();
        if (editor instanceof JFormattedTextField) {
            ((JFormattedTextField) editor).select(0,
                    ((JFormattedTextField) editor).getText().length());
        } else if (editor instanceof JTextField) {
            ((JTextField) editor).selectAll();
        }
    }
}

After reading a lot of documentation and posts, it became clear that the most appropriate way to address the problem was through the use of key-bindings, basically and after all read, the solution was to assign the behavior of the Tab key to the Enter key, and so I did.

private void tableConfiguration() {
    //Configuramos la tabla para que en el caso de que pierda el foco finalice la edición 
    putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);        
    //Cambiamos el comportamiento por defecto de la tecla enter para que actue como TAB
    getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
            .put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "selectNextColumnCell");
    // cambiamos Shift+Enter para que se comporte como Shift+Tab
    getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
            .put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_MASK),
            "selectPreviousColumnCell");
    //configuramos el comportamiento por defecto que queremos que tenga nuestro grid
    setSelectionMode(ListSelectionModel.SINGLE_SELECTION);//seleccion simple de celda
    setCellSelectionEnabled(true);//muestra la celda activa seleccionada
    getTableHeader().setReorderingAllowed(false);//no permite reordenar por columnas
    setRowHeight(26);//altura de la fila
}

As you can see in the code section, they were assigned to Enter and Shift+Enter the behaviors of Tab the Shift+Tab keys.

The problem I have is that the Enter key has an unexpected behavior. When the cell takes focus, enters directly into edit mode, when I press the Enter key it finishes the editing but it doesn't transfer the focus to the next cell, I need to press again the Enter key to get that. Tab and Shift+Tab keys works as expected and curiously, Shift+Enter keys works well too, finishing editing, moving to the previous cell and starting in edit mode.

I have tried to correct that behavior following different strategies, overriding the method editingStopped of the JTable class, through the TableCellEditor class, using Listeners in diferent ways, etc, and I have not been able to correct that behavior so I'm stuck now. Anyone have a suggestions or the solution? what am I doing wrong?

Greetings,

CodeCat
  • 63
  • 1
  • 6
  • ((JTextField) editor).selectAll(); should be inside invokeLater (moving this event to the end of EDT queue) – mKorbel Jun 25 '16 at 11:04
  • hello @mKorbel thanks for your help, I did as you suggested but it has no efect on the behaviour of the JTable, it still acts as described aboved, `Tab`, `Shift+Tab` and `Shift+Enter` works as wished, finishing the editing of the cell, changing to the next cell using `Tab`, to the previous one using `Shift+Tab` or `Shift+Enter`, and re-enter edit mode in the new cell automatically, meanwhile, you must press the `Enter` key twice to exit the editing and switch to the next cell to edit it. I'm looking for the way to avoid this behaviour. Thanks – CodeCat Jul 04 '16 at 12:29

2 Answers2

3

As shown here, you can obtain a reference to the original Action associated with "selectNextColumnCell", which is normally associated with Tab, and evoke it in your implementation of editingStopped(). The simplified example below also associates the action with pressing Enter. The result is that pressing Enter will have the same effect as pressing Tab, even if the keypress also concludes editing.

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.event.ChangeEvent;

public class TestTableKeyBinding {

    private final String name = "selectNextColumnCell";

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new TestTableKeyBinding();
        });
    }

    TestTableKeyBinding() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        String[] headers = new String[]{"apples", "bananas"};
        String[][] data = new String[][]{{"1", "2"}, {"3", "4"}, {"5", "6"}};
        JTable table = new JTable(data, headers) {
            @Override
            public void editingStopped(ChangeEvent e) {
                super.editingStopped(e);
                this.getActionMap().get(name).actionPerformed(
                    new ActionEvent(this, ActionEvent.ACTION_FIRST, name));
            }
        };
        table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
            .put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), name);
        table.setCellSelectionEnabled(true);
        f.add(new JScrollPane(table));
        f.pack();
        f.setSize(new Dimension(320, 240));
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • thanks but sadly it doesn't work as I want, if you are in edit mode `Enter` moves to the next cell but, `Shift+Enter` moves too, and if you use the `Tab` key it has now an strange behabiour cause the editing is not the same as the focused cell. my only problem is how to change this particular behaviour of the `Enter`key that the other keys don't have. – CodeCat Jul 04 '16 at 12:22
  • I don't understand. Please edit your question to include a [mcve], based on my simplified example above, that shows your current approach. – trashgod Jul 04 '16 at 14:29
  • hello trashgod and thanks in advance for your help, as I can't put a complete example here, I uploaded it into my [Google drive](https://drive.google.com/file/d/0B6L3Kw_8T4q-dEpvVHE0SHFhekk/view?usp=sharing) where you can get it and take a look of what I was saying in my previous comment. Specially please, take look the behaviour of using the `Tab` key and the `Shift` key. Again thanks in advance. Greetings. – CodeCat Jul 12 '16 at 10:41
0

I think you have added JTextField using DefaultCellEditor to your JTable cell.so when you Press Left or Right key then focus come from JTable cell to JTextField that's why you should add keyListener to your JTextField and on Enter KeyPress move focus to the next cell of JTable using JTable.changeSelection() and JTable.editCellAt(). I hope it helps.

hemant
  • 27
  • 6