Java 如何防止JTable在指定列中接受特定输入?

Java 如何防止JTable在指定列中接受特定输入?,java,swing,jtable,Java,Swing,Jtable,我试图得到一个JTable,它只接受每列特定格式的输入。例如,在一个有5列的表中,索引3和4处的表应该只接受数值 我知道RowFilter和RowFilter.regexFilter。。。因为,但这会隐藏整行,而不仅仅是放弃更改,甚至会阻止在添加行后立即显示空行。以下是我尝试将其用作示例的方式: public static void main(String[] args) { // Create empty table with 5 columns JTable table =

我试图得到一个JTable,它只接受每列特定格式的输入。例如,在一个有5列的表中,索引3和4处的表应该只接受数值

我知道RowFilter和RowFilter.regexFilter。。。因为,但这会隐藏整行,而不仅仅是放弃更改,甚至会阻止在添加行后立即显示空行。以下是我尝试将其用作示例的方式:

public static void main(String[] args) {
    // Create empty table with 5 columns
    JTable table = new JTable(new DefaultTableModel(new String[][] {}, new String[] { "String", "String", "String", "Num", "Num" }));

    // Create a new table row sorter
    TableRowSorter<TableModel> sorter = new TableRowSorter<>(table.getModel());

    // Filter columns 4 and 5 to only contain numbers
    sorter.setRowFilter(RowFilter.regexFilter("[0-9]+", 3, 4));

    // Apply the sorter to the table
    table.setRowSorter(sorter);

    // Boilerplate JFrame setup in case you want to run this
    JFrame frame = new JFrame("MRE");
    JPanel contentPane = new JPanel();
    JButton addRow = new JButton("Add Row");
    addRow.addActionListener((event) -> ((DefaultTableModel) table.getModel()).addRow(new String[] {}));
    contentPane.add(new JScrollPane(table));
    contentPane.add(addRow);
    frame.setSize(500, 500);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setContentPane(contentPane);
    frame.setVisible(true);
}

TL;DR:如果输入的值不允许,我希望单元格恢复其以前的值,或者在键入阶段甚至不接受错误的输入。

我通过重写JTable的editingStoppedChangeEvent e方法成功地做到了这一点。您可能应该使用TableCellEditor来实现这一点,但我发现这更容易:

public class MyTable extends JTable {

    // Contains the check for each column
    private final Map<Integer, Function<String, Boolean>> checks = new HashMap<>();

    public STable(TableModel model) {
        super(model);

        // Fill the map
        checks.put(0, (str) -> ...);
        checks.put(3, (str) -> ...);
        checks.put(4, (str) -> ...);
    }

    @Override
    public void editingStopped(ChangeEvent e) {
        String value = getCellEditor().getCellEditorValue().toString();

        final Function<String, Boolean> checker = checks.get(getSelectedColumn());
        if (checker != null && !checker.apply(value))
            getCellEditor().cancelCellEditing();
        else
            super.editingStopped(e);
    }

}

另外,我没有尝试过,但是camickr关于覆盖GetColumnClasint列的建议听起来似乎可以很好地工作。我没有尝试,因为我需要更多的复杂性。

我想说的是,提供一个合适的单元格编辑器。例如,在一个有5列的表中,索引3和4处的那些应该只接受数值。-这与划船分拣机无关。您需要重写getColumnClass方法以返回这些列的Integer.class。该表将选择一个只允许数值的整数编辑器。我修改了我的代码以更好地适应mre的描述。尽管看起来很奇怪,但进一步减少代码片段的方法更不像是MRE/SSCCE。问题是&这是一个常见的误解,它不完全是关于最小/短的。我成功地做到了这一点,祝贺你解决了这个问题&+1感谢你的反馈。话虽如此,请再次访问,尤其是上的页面,该页面将更详细地回顾构成MRE/SSCCE标签的其他元素。发布一个会帮助别人帮助你。@AndrewThompson更不像mre。你说得对。因为这篇文章的第一个版本几乎是你能为这个问题提供的最好的mre,我希望这次你能让我解释一下原因。让我们看一下SCSCE的每一个点,好吗?短:25行带注释和间隙:远低于100行。TfT、PrS和SC:本例中的每一行都有它的用途,并有助于使其成为最可运行的。更正:有些行可能太长了,但这不会影响可读性,而且格式也很好。请原谅我听起来有些自大,但我在这里受到了注释长度的限制。本质上我要说的是,这个例子满足了你发布的链接中几乎所有的要求,因此应该被认为是一个有效的mre。如果你认为没有,请解释原因。哦,为了记录在案,我回到了这篇文章的原始版本。