简体   繁体   中英

JTable edit on keypress

I am trying to programatically start editing third column of current row in a JTable on a keypress.

I've implemented a KeyListener which in keyReleased() contains this code

if (e.getKeyCode() == KeyEvent.VK_ENTER)
{
    myTab.changeSelection(myTab.getSelectedRow(), 2, true, false);
    myTab.editCellAt(myTab.getSelectedRow(), 2);
}

When I release enter, the cell is indeed editable (I can type at the end), but there is no caret.

When I click with mouse, behaviour is as expected (I can edit and carret is present).

Also, I've noticed that on keyrelease, my celleditor is null, and on mouseclick it is not null.

What am I doing wrong?

Avoid KeyListener , it is unreliable when it comes to focus and the order in which the events are dispatched (it's possible to have they key consumed BEFORE your listener, so you would never be notified).

Use key bindings instead

InputMap im = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
ActionMap am = table.getActionMap();

KeyStroke enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);

im.put(enterKey, "Action.enter");
am.put("Action.enter", new AbstractAction() {
    public void actionPerformed(ActionEvent evt) {
        table.changeSelection(table.getSelectedRow(), 2, false, false);
        if (!table.editCellAt(table.getSelectedRow(), 2)) {
            JOptionPane.showMessageDialog(table, "Failed to start cell editing");
        }
    }
});

I'm also suspicious of this myTab.changeSelection(myTab.getSelectedRow(), 2, true, false); call. The JavaDocs basically say...

toggle: true, extend: false. If the specified cell is selected, deselect it. If it is not selected, select it.

Which suggest to me, if the cell is currently selected, it will be made unselected.

Updated with working example

public class TestTableEditor {

    public static void main(String[] args) {
        new TestTableEditor();
    }

    private JTable table;

    public TestTableEditor() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                table = new JTable(new MyTableModel());
                InputMap im = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
                ActionMap am = table.getActionMap();

                KeyStroke enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);

                im.put(enterKey, "Action.enter");
                am.put("Action.enter", new AbstractAction() {
                    public void actionPerformed(ActionEvent evt) {
                        table.changeSelection(table.getSelectedRow(), 1, false, false);
                        if (!table.editCellAt(table.getSelectedRow(), 1)) {
                            JOptionPane.showMessageDialog(table, "Failed to start cell editing");
                        }
                    }
                });

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(table));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class MyTableModel extends AbstractTableModel {

        @Override
        public int getRowCount() {
            return 1;
        }

        @Override
        public int getColumnCount() {
            return 3;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            Object value = null;
            switch (columnIndex) {
                case 0:
                    value = "Can't edit";
                    break;
                case 1:
                    value = "Edit me";
                    break;
                case 2:
                    value = "Can't edit";
                    break;
            }
            return value;
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return columnIndex == 1;
        }
    }
}

Updated

Of all the stupid, painful, hard to find ...

Add table.setSurrendersFocusOnKeystroke(true); to your code...

Sets whether editors in this JTable get the keyboard focus when an editor is activated as a result of the JTable forwarding keyboard events for a cell. By default, this property is false, and the JTable retains the focus unless the cell is clicked.

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