java - 允许我只输入单个数字的JTable单元格/列

时间:2014-03-26 10:17:55

标签: java swing jtable tablecelleditor

java - 我想要一个JTable单元格/列,只允许我输入一位数字(如1到9)。我怎么能这样做?

我试过这个,但我按下的号码在单元格中出现两次。

table.addKeyListener(new KeyAdapter() {         
        public void keyPressed(KeyEvent e) {
            System.out.println("pressed..."+e.getKeyChar());
            char key = e.getKeyChar();
            int selectedColumn = table.getSelectedColumn();
            int selectedRow = table.getSelectedRow();
            if(table.getValueAt(selectedRow, selectedColumn) == null)
            table.setValueAt(key, selectedRow, selectedColumn);
        }
   });

2 个答案:

答案 0 :(得分:5)

请勿使用KeyListener。您可以执行的操作是使用JTextField TableCellEditor,只需将DocumentFilter添加到仅允许数字的JTextField

这是一个正在运行的例子

import javax.swing.DefaultCellEditor;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellEditor;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.DocumentFilter.FilterBypass;

public class JTableNumberColumn {

    public JTableNumberColumn() {
        JFrame frame = new JFrame();
        JTextField field = createTextField();
        frame.add(new JScrollPane(createTable(field)));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private JTextField createTextField() {
        JTextField field = new JTextField();
        ((AbstractDocument) field.getDocument()).setDocumentFilter(new DocumentFilter() {
            @Override
            public void insertString(FilterBypass fb, int off, String str, AttributeSet attr)
                    throws BadLocationException {
                fb.insertString(off, str.replaceAll("\\D++", ""), attr);  // remove non-digits
            }

            @Override
            public void replace(FilterBypass fb, int off, int len, String str, AttributeSet attr)
                    throws BadLocationException {
                fb.replace(off, len, str.replaceAll("\\D++", ""), attr);  // remove non-digits
            }
        });
        return field;
    }

    private JTable createTable(final JTextField field) {
        String[] cols = {"Only Numbers", "Col 2", "Col 3"};
        String[][] data = {{null, null, null}, {null, null, null}, {null, null, null}};
        final TableCellEditor editor = new DefaultCellEditor(field);
        JTable table = new JTable(data, cols) {
            @Override
            public TableCellEditor getCellEditor(int row, int column) {
                int modelColumn = convertColumnIndexToModel(column);

                if (modelColumn == 0) {
                    return editor;
                } else {
                    return super.getCellEditor(row, column);
                }
            }
        };
        return table;
    }

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

编辑1

我可能误解了你的问题。如果您只想允许一个号码。然后,您可以使用JFormattedTextField MaskFormatter作为TableCellEditor。这是一个例子

import javax.swing.DefaultCellEditor;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellEditor;
import javax.swing.text.MaskFormatter;

public class JTableNumberColumn {

    public JTableNumberColumn() {
        JFrame frame = new JFrame();
        JFormattedTextField field = createFormattedTextField();
        frame.add(new JScrollPane(createTable(field)));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }


    private JFormattedTextField createFormattedTextField() {
        JFormattedTextField field = new JFormattedTextField(createFormatter("#"));
        return field;
    }

    protected MaskFormatter createFormatter(String s) {
        MaskFormatter formatter = null;
        try {
            formatter = new MaskFormatter(s);
        } catch (java.text.ParseException exc) {
            System.err.println("formatter is bad: " + exc.getMessage());
            System.exit(-1);
        }
        return formatter;
    }

    private JTable createTable(final JFormattedTextField field) {
        String[] cols = {"Only Numbers", "Col 2", "Col 3"};
        String[][] data = {{null, null, null}, {null, null, null}, {null, null, null}};
        final TableCellEditor editor = new DefaultCellEditor(field);
        JTable table = new JTable(data, cols) {
            @Override
            public TableCellEditor getCellEditor(int row, int column) {
                int modelColumn = convertColumnIndexToModel(column);

                if (modelColumn == 0) {
                    return editor;
                } else {
                    return super.getCellEditor(row, column);
                }
            }
        };
        return table;
    }

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

编辑2

它引起了我的注意,我也忽略了你只想要1-9而不是0-9的事实。在这种情况下,我只会坚持使用JTextField DocumentFilter的第一个选项,但在过滤器中,检查输入的长度并将正则表达式更改为仅允许1-9。

这是示例

import javax.swing.DefaultCellEditor;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellEditor;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.DocumentFilter.FilterBypass;

public class JTableNumberColumn {

    public JTableNumberColumn() {
        JFrame frame = new JFrame();
        JTextField field1 = createTextField();
        frame.add(new JScrollPane(createTable(field1)));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private JTextField createTextField() {
        final JTextField field = new JTextField();
        ((AbstractDocument) field.getDocument()).setDocumentFilter(new DocumentFilter() {
            @Override
            public void insertString(FilterBypass fb, int off, String str, AttributeSet attr)
                    throws BadLocationException {
                int length = field.getDocument().getLength();
                if (length + str.length() <= 1) {
                    fb.insertString(off, str.replaceAll("[^1-9]", ""), attr);  // remove non-digits
                }
            }

            @Override
            public void replace(FilterBypass fb, int off, int len, String str, AttributeSet attr)
                    throws BadLocationException {
                int length = field.getDocument().getLength();
                if (length + str.length() <= 1) {
                    fb.replace(off, len, str.replaceAll("[^1-9]", ""), attr);  // remove non-digits
                }
            }
        });
        return field;
    }


    private JTable createTable(final JTextField field) {
        String[] cols = {"Only Numbers", "Col 2", "Col 3"};
        String[][] data = {{null, null, null}, {null, null, null}, {null, null, null}};
        final TableCellEditor editor = new DefaultCellEditor(field);
        JTable table = new JTable(data, cols) {
            @Override
            public TableCellEditor getCellEditor(int row, int column) {
                int modelColumn = convertColumnIndexToModel(column);

                if (modelColumn == 0) {
                    return editor;
                } else {
                    return super.getCellEditor(row, column);
                }
            }
        };
        return table;
    }

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

答案 1 :(得分:0)

一种方法是实现自己的TableModel(无论如何我会这样做)并实现setValueAt(Object,int,int)方法。在该方法中验证,如果值不好则不设置值(包括放置JDialog或其他适当的值)。以下是一些代码:

public class MyTableModel extends AbstractTableModel {

...

@Override
public void setValueAt(Object o, int i, int j) {
    if (o instanceof String) {
        char c = ((String) o).charAt(0);

        if (((String) o).length() == 1 && c >= '0' && c <= '9') {
            data[i][j] = Integer.valueOf(((String) o).substring(0, 1));
            return;
        }
    }
    JOptionPane.showMessageDialog(null, "Must input a number from 0-9");
}

我花了很长时间才发布其他人回答的帖子!无论如何,因为我的方法不同,我想我会把它包括在内。我正在制定一个有效的计划。

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

public class TestTable {

    public static void main(String[] args) {
        TestTable tt = new TestTable();
        tt.init();
    }

    private void init() {
        // Make model
        MyModel model = new MyModel ();
        JTable table = new JTable(model);

        // Add to a frame
        JScrollPane pane = new JScrollPane(table);
        JFrame frame = new JFrame("Test");
        frame.add(pane);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

}

class MyModel extends AbstractTableModel {

    // Just some dummy data
    Integer[][] data = new Integer[10][6];

    // Init the dummy data
    public MyModel() {
        super();
        for (int i = 0; i < data.length; i++) {
            Integer[] is = data[i];
            for (int j = 0; j < is.length; j++) {
                data[i][j] = 20 * i + j;
            }
        }
    }

    @Override
    public int getRowCount() {
        return data.length;
    }

    @Override
    public int getColumnCount() {
        return data[0].length;
    }

    @Override
    public Object getValueAt(int i, int j) {
        return data[i][j];
    }

    // Makes cells editable
    @Override
    public boolean isCellEditable(int i, int j) {
        return true;
    }

    @Override
    public void setValueAt(Object o, int i, int j) {
        if (o instanceof String) {
            char c = ((String) o).charAt(0);

            if (((String) o).length() == 1 && c >= '0' && c <= '9') {
                data[i][j] = Integer.valueOf(((String) o).substring(0, 1));
                return;
            }
        }
        JOptionPane.showMessageDialog(null, "Must input a number from 0-9");
    }
}