简体   繁体   English

停止JTable仅在聚焦并按下键时才可编辑

[英]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. 我编写了一个自定义的DefaultCellEditor以便在示例JTablelength列中键入内容时只能输入数字。

To do this I added a KeyListener to the JTextField that is used as the editor component. 为此,我向用作编辑器组件的JTextField添加了一个KeyListener 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 停止JTable仅在聚焦并按下键时才可编辑

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. 我编写了一个自定义的DefaultCellEditor,以便在示例JTable的长度列中键入内容时只能输入数字。

No need to write a custom editor. 无需编写自定义编辑器。 Just use a JFormattedTextField as the editor instead of a JTextField: 只需使用JFormattedTextField而不是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 ) . 看一下CellEditor.isCellEditable( EventObject anEvent ) AbstractCellEditor and DefaultCellEditor implement the CellEditor interface. AbstractCellEditorDefaultCellEditor实现CellEditor接口。

You can override this method to return false in case the EventObject is instance of type KeyEvent . 如果EventObjectKeyEvent类型的实例,则可以重写此方法以返回false。 Otherwise return super.isCellEditable( anEvent ) . 否则返回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 . 参照TT。的 答案 ,并用DefaultCellEditor像原来的问题确实是在你加入这个方法简单DefaultCellEditor

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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