停止 JTable 仅在获得焦点并按下按键时才可编辑

Stop JTable being editable only when focussed and key pressed

我写了一个自定义 DefaultCellEditor,这样当我在示例的 length 列中键入内容时 JTable 我只能在其中输入数字。

为此,我向用作编辑器组件的 JTextField 添加了一个 KeyListener。虽然如果您双击单元格以编辑值这很有效,但如果您单击该单元格一次然后开始键入它就不起作用。

如果用户单击单元格一次然后开始键入,我如何防止用户能够编辑单元格,同时仍然允许用户双击单元格开始编辑它?

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());
    }
}

看看CellEditor.isCellEditable( EventObject anEvent ). AbstractCellEditor and DefaultCellEditor implement the CellEditor界面。

如果 EventObject 是类型 KeyEvent 的实例,您可以将此方法重写为 return false。否则 return super.isCellEditable( anEvent ).

参考 TT.'s 并像原始问题一样使用 DefaultCellEditor 就像在 DefaultCellEditor.

中添加此方法一样简单
public boolean isCellEditable(EventObject anEvent) {
    if (anEvent instanceof MouseEvent) {
        return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;
    }
    return false;
}

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.

无需编写自定义编辑器。只需使用 JFormattedTextField 作为编辑器而不是 JTextField:

有点像。

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