简体   繁体   中英

Inconsistent behavior when editing JTable

I want to create a JTable that has the following properties:

  • A single click in a cell will start editing (done - via setClickCountToStart(1))
  • Tabbing will take the user to the next cell (already the default)
  • Pressing enter will invoke some external method

I tried to implement this last item by adding an item to the ActionMap of the text field of a DefaultCellEditor. This works under the following sequence:

  • Click in a cell
  • Type some text
  • Click enter

But if I navigate to any other cell via tab, edit that cell, then click enter, this does not work. The Action is only fired if I hit enter in the cell that I started editing via a click. If I got to that cell by tabbing or using the arrow keys, it does not work.

I think maybe the focus is still on the cell where I started editing? I noticed that if I click/edit/tab a few times, then click in the currently edited cell before pressing enter, that seems to work.

Does tabbing take the user to the next cell without transferring focus? Any help would be appreciated.

package jtabletest;

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.DefaultCellEditor;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class JTableKeyMap {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(JTableKeyMap::createAndDisplayGui);
    }


    public static void createAndDisplayGui() {
        final JTable table = new JTable(4, 4);
        final JTextField cell = new JTextField();
        final DefaultCellEditor cellEditor = new DefaultCellEditor(cell);
        cellEditor.setClickCountToStart(1);

        table.setDefaultEditor(Object.class, cellEditor);

        KeyStroke enterKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
        String enterText = "enterKeyPressed";

        final InputMap iMap = cell.getInputMap(JComponent.WHEN_FOCUSED);
        iMap.put(enterKeyStroke, enterText);

        AbstractAction action = new AbstractAction() {
            @Override
            public void actionPerformed(final ActionEvent e) {
                System.out.println("Callback for key event");
                cellEditor.stopCellEditing();
            }
        };

        ActionMap aMap = cell.getActionMap();
        aMap.put(enterText, action);

        aMap.put(KeyEvent.getKeyText(KeyEvent.VK_ENTER), new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Callback for key event");

                cellEditor.stopCellEditing();
            }
        });

        JScrollPane scrollPane = new JScrollPane(table);


        final JFrame frame = new JFrame("Table Test");
        frame.setContentPane(scrollPane);
        frame.setPreferredSize(scrollPane.getPreferredSize());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}

Add the following when you create you JTable:

table.setSurrendersFocusOnKeystroke(true);

This will give the editor focus if you just start typing when a cell has focus. Then the editor will respond to your key bindings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM