Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JTable - Getting a cell into Edit mode on pressing Tab

Tags:

java

swing

jtable

This is possibly has a trivial solution, but I am at the end of my tether so I hope somebody can help out.

I use a JTable which has a custom renderer and a custom editor for a set of columns.
The renderer uses a JLabel component and the editor uses a JSpinner component.
Our users want to be able to enter values in a column, and then press TAB or ENTER to move to the next editable cell in the table.
If I understand correctly, this is the default behaviour for a JTable.

However, this doesn't seem to work correctly for me. Until the user clicks on the cell, only the JLabel is displayed.
The JSpinner (i.e. CellEditor) is only displayed when a user double clicks on the cell. So, it looks like the cell is going into "edit" mode only on MouseEvents, but not when it has focus.

How do I get the cell to go into edit mode as soon as it has focus?

like image 292
Luhar Avatar asked Jun 10 '10 09:06

Luhar


People also ask

Is cell editable JTable?

The isCellEditable() method of JTable (or the TableModel) controls whether a cell is editable or not. By default it just return "true". So you can override the method to return a boolean value that is set by your "Modify" button.

How can we add insert a JButton to JTable cell in Java?

We can add or insert a JButton to JTable cell by customizing the code either in DefaultTableModel or AbstractTableModel and we can also customize the code by implementing TableCellRenderer interface and need to override getTableCellRendererComponent() method.


3 Answers

Here's a code snippet that I put together for a project that I was working on. The code has been tested and verified for a table that has non-editable cells in the first and last column. The class restricts tabbing to only the editable cells of the table. It also supports shift-tabbing to tab in reverse.

public class JTableCellTabbing {
/**
 * 
 * Creates a new {@code JTableCellTabbing} object.
 *
 *
 */
private JTableCellTabbing() {        
}

/**
 * 
 * Set Action Map for tabbing and shift-tabbing for the JTable
 *
 *
 * @param theTable - Jtable with NRows and MCols of cells
 * @param startRow - valid start row for tabbing [ 0 - (numRows-1) ]
 * @param numRows - Number of rows for tabbing
 * @param startCol - valid start col for tabbing [ 0 - (numCols-1) ]
 * @param numCols -  Number of columns for tabbing
 */
@SuppressWarnings("serial")
static public void setTabMapping(final JTable theTable, final int startRow, final int numRows, final int startCol, final int numCols) {
    if (theTable == null) {
        throw new IllegalArgumentException("theTable is null");
    }

    // Calculate last row and column for tabbing
    final int endRow = startRow + (numRows - 1);
    final int endCol = startCol + (numCols - 1);

    // Check for valid range
    if ((startRow > endRow) || (startCol > endCol)) {
        throw new IllegalArgumentException("Table Size incorrect");            
    }

    // Get Input and Action Map to set tabbing order on the JTable
    InputMap im = theTable.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
    ActionMap am = theTable.getActionMap();

    // Get Tab Keystroke
    KeyStroke tabKey = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);                    
    am.put(im.get(tabKey), new AbstractAction() {

        @Override
        public void actionPerformed(ActionEvent e) {
            int row = theTable.getSelectedRow();
            int col = theTable.getSelectedColumn();

            col++;

            // Move to next row and left column
            if (col > endCol) {
                col = startCol;
                row++;
            }

            // Move to top row
            if (row > endRow ) {
                row = startRow;
            }

            // Move cell selection
            theTable.changeSelection(row, col, false, false);
        }            
    });

    // Get Shift tab Keystroke
    KeyStroke shiftTab = 
        KeyStroke.getKeyStroke(KeyEvent.VK_TAB, java.awt.event.InputEvent.SHIFT_DOWN_MASK);                    
    am.put(im.get(shiftTab), new AbstractAction() {

        @Override
        public void actionPerformed(ActionEvent e) {
            int row = theTable.getSelectedRow();
            int col = theTable.getSelectedColumn();

            col--;

            // Move to top right cell
            if (col < startCol) {
                col = endCol;
                row--;
            }

            // Move to bottom row
            if (row < startRow ) {
                row = endRow;
            }

            // Move cell selection
            theTable.changeSelection(row, col, false, false);
        }            
    });                    
}

}

And here's how the class is used for your table:

JTable myTable = new JTable();
// Set up table attributes....
JTableCellTabbing.setTabMapping(myTable, 0, NUM_ROWS, 1, (NUM_COLS-1));
like image 97
Steven Lee Avatar answered Nov 10 '22 00:11

Steven Lee


Thank you n00213f. The thread and example from your post were helpful. By overloading the changeSelection method in JTable as hinted to in the thread, JTable checks if a cell is editable every time the selection is changed. If the cell is editable, it will show the CellEditor and transfer focus to the editor component.

For completeness, here is my solution:

  JTable myTable = new javax.swing.JTable()
  {
            public void changeSelection(final int row, final int column, boolean toggle, boolean extend)
            {
                super.changeSelection(row, column, toggle, extend);
                myTable.editCellAt(row, column);
                myTable.transferFocus();
            }
  };
like image 31
Luhar Avatar answered Nov 10 '22 00:11

Luhar


You can achieve this programatically, you simply listen to the focus events on the cell, on focus and editing allowed, start editing.

More on this thread and example

like image 42
n002213f Avatar answered Nov 10 '22 01:11

n002213f