简体   繁体   中英

Stop JTable being editable only when focussed and key pressed

I wrote a custom DefaultCellEditor so that when I type in the length column of the example JTable I can not enter anything but numbers in it.

To do this I added a KeyListener to the JTextField that is used as the editor component. Whilst this works great if you double click on the cell to edit the value, it does not work if you click on the cell once and then start typing.

How can I prevent the user from being able to edit the cell if they click on the cell once and then start typing, whilst still allowing the user to double click on the cell to start editing it?

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.lang.reflect.Constructor;

import javax.swing.DefaultCellEditor;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.border.LineBorder;

@SuppressWarnings("serial")
public class JTableTest extends JFrame {
    private JTableTest() {
        super("JTable Test");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(1, 1));
        createPanel();
        pack();
        setVisible(true);
    }

    JPanel panel = new JPanel(new GridLayout(1, 1));
    JScrollPane scroll;

    private void createPanel() {
        Object[] headers = {"Length", "Title"};
        Object[][] sampleData = {{"673", "Bat Outta Hell"},
                {"358", "Spanish Train"},
                {"673", "Bat Outta Hell"}};
        JTable table = new JTable(sampleData, headers);
        table.setDefaultEditor(Object.class, new NumEditor());
        scroll = new JScrollPane(table);
        panel.add(scroll);
        getContentPane().add(panel);
    }

    private class NumEditor extends DefaultCellEditor {
        Class<?>[] argTypes = new Class<?>[]{String.class};
        Constructor<?> constructor;
        Object value;

        public NumEditor() {
            super(new JTextField());
            getComponent().setName("Table.editor");
        }

        public boolean stopCellEditing() {
            String s = (String)super.getCellEditorValue();
            try {
                if ("".equals(s)) {
                    if (constructor.getDeclaringClass() == String.class) {
                        value = s;
                    }
                    return super.stopCellEditing();
                }
                value = constructor.newInstance(new Object[]{s});
            }
            catch (Exception e) {
                ((JComponent)getComponent()).setBorder(new LineBorder(Color.red));
                return false;
            }
            return super.stopCellEditing();
        }

        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            this.value = null;
            ((JComponent)getComponent()).setBorder(new LineBorder(Color.black));
            try {
                Class<?> type = table.getColumnClass(column);

                if (type == Object.class) {
                    type = String.class;
                }

                KeyListener kL = new KeyListener() {
                    public void keyPressed(KeyEvent e) {

                    }
                    public void keyReleased(KeyEvent e) {

                    }
                    public void keyTyped(KeyEvent e) {
                        char c = e.getKeyChar();
                        if(Character.isDigit(c)){

                        } else {
                            e.consume();
                        }
                    }
                };

                if(column == 0)
                    ((JComponent)getComponent()).addKeyListener(kL);
                else
                    ((JComponent)getComponent()).removeKeyListener(kL);

                constructor = type.getConstructor(argTypes);
            }
            catch (Exception e) {
                return null;
            }
            return super.getTableCellEditorComponent(table, value, isSelected, row, column);
        }

        public Object getCellEditorValue() {
            return value;
        }
    }

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

Stop JTable being editable only when focussed and key pressed

Well, this is the default behaviour when you edit a cell with string data.

Why should it be any different when you try to enter numeric data?

I wrote a custom DefaultCellEditor so that when I type in the length column of the example JTable I can not enter anything but numbers in it.

No need to write a custom editor. Just use a JFormattedTextField as the editor instead of a JTextField:

Something like.

MaskFormatter format = new MaskFormatter("######");
JFormattedTextField ftf = new JFormattedTextField( format );
DefaultCellEditor dce = new DefaultCellEditor( ftf );
table.getColumnModel().getColumn(2).setCellEditor(dce);

Take a look at CellEditor.isCellEditable( EventObject anEvent ) . AbstractCellEditor and DefaultCellEditor implement the CellEditor interface.

You can override this method to return false in case the EventObject is instance of type KeyEvent . Otherwise return super.isCellEditable( anEvent ) .

Referring to TT.'s answer and using a DefaultCellEditor like the original question does it is as simple as adding this method in your DefaultCellEditor .

public boolean isCellEditable(EventObject anEvent) {
    if (anEvent instanceof MouseEvent) {
        return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;
    }
    return false;
}

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