Question

I have a keylistener on jtable so that when someone presses enter some calculations happen. However, this only happens if the person is not editing. I would like to apply this action when a person finishes editing a cell and is pressing enter to finish and close the editing.

I cannot figure this out, anyone ever did this or know how to?

Basically, now for the action to be done, people must press enter twice, one to end the editing and another for the action that I want to happen, I would like to make it needed only once, while editing.

Thank you

Was it helpful?

Solution 3

You can override JTable.editingStopped, which is invoked when editing is finished and apply your actions in that method.

EDIT:

JTable.editingStopped was not designed for application extension. To avoid complications, in particular platform dependent ones, a better approach is to override model's setValueAt or register a TableModelListener. Here is an example:

import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;

public class DemoTable3 {
    private static void createAndShowUI() {
        JFrame frame = new JFrame("DemoTable");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Object[][] rows = { { "Column 1", "Column 2" },
                { "Column 1", "Column 2" } };
        Object[] columns = { "Column 1", "Column 2" };

        DefaultTableModel model = new DefaultTableModel(rows, columns);
        model.addTableModelListener(new TableModelListener() {
            @Override
            public void tableChanged(TableModelEvent e) {
                System.out.println("apply additional action");
            }
        });

        JTable table = new JTable(model);
        frame.add(new JScrollPane(table));
        frame.setLocationByPlatform(true);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowUI();
            }
        });
    }
}

Another alternative is to add CellEditorListener to catch editingStopped events. For example:

import javax.swing.*;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.DefaultTableModel;

public class DemoTable2 {

    private static void createAndShowUI() {
        JFrame frame = new JFrame("DemoTable");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Object[][] rows = { { "Column 1", "Column 2" },
                { "Column 1", "Column 2" } };
        Object[] columns = { "Column 1", "Column 2" };

        final JTable table = new JTable(new DefaultTableModel(rows, columns));

        table.getDefaultEditor(String.class).addCellEditorListener(
                new CellEditorListener() {
                    public void editingCanceled(ChangeEvent e) {
                        System.out.println("editingCanceled");
                    }

                    public void editingStopped(ChangeEvent e) {
                        System.out.println("editingStopped: apply additional action");
                    }
                });

        frame.add(new JScrollPane(table));
        frame.setLocationByPlatform(true);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowUI();
            }
        });
    }
}

Also look at a Table Cell Listener by @camickr which offers custom processing of the edits.

OTHER TIPS

You could customize your own editor. Using DefaultCellEditor Instead using KeyListener you should use KeyBindings.

See this example.

            JTable table = new JTable(myModel);
            JTextField cell = new JTextField();
            final TableCellEditor cellEditor = new DefaultCellEditor(cell);
            table.getColumnModel().getColumn(column).setCellEditor(cellEditor);
            InputMap iMap = cell.getInputMap(JComponent.WHEN_FOCUSED);
            iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),    KeyEvent.getKeyText(KeyEvent.VK_ENTER));
            ActionMap aMap = cell.getActionMap();
            aMap.put(KeyEvent.getKeyText(KeyEvent.VK_ENTER), new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if(callSomeOperationsIsOk()){
                      cellEditor.stopCellEditing();
                    }else{
                      cellEditor.cancelCellEditing();
                    }
                }
            });
    }

Read more in tutorials How to use Tables, and perhaps you have the same trouble that i have see my previous question

I have a keylistener on jtable so that when someone presses enter some calculations happen. However, this only happens if the person is not editing. I would like to apply this action when a person finishes editing a cell and is pressing enter to finish and close the editing.

  • TableCellEditor hasn't something with KeyListener added to JTable

Basically, now for the action to be done, people must press enter twice, one to end the editing and another for the action that I want to happen, I would like to make it needed only once, while editing.

  • JComponents (used as TableCellEditor) by default to react to ENTER key pressed

  • don't to put JComponent to the TableModel, there should be stored only value painted by TableCellRenderer and initial value for TableCellEditor

  • TableCellEditor is temporarily JComponent, you have to add KeyBindings to invoke stopCellEditing in the case that JComponents used as TableCellEditor doesn't to react to ENTER key pressed


Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top