如何防止 JTable 在指定列中获取特定输入?

How do I prevent a JTable from taking a certain input in the specified column?

我正在尝试让 JTable 只接受每列特定格式的输入。例如,在具有 5 列的 table 中,索引 3 和 4 处的列应该只接受数值。

我知道 RowFilterRowFilter.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 的 editingStopped(ChangeEvent 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 的覆盖 getColumnClass(int column) 的建议听起来效果不错。我没有尝试,因为我需要比这更复杂的东西。