Как пометить ввод в ячейку JTable как недействительный? - PullRequest
9 голосов
/ 23 сентября 2011

Если я возьму JTable и укажу класс столбца для его модели следующим образом:

   DefaultTableModel model = new DefaultTableModel(columnNames, 100) {
       @Override
        public Class<?> getColumnClass(int columnIndex) {
            return Integer.class;
        }};

Затем, когда пользователь пытается ввести значение double в таблицу, Swing автоматически отклоняетinput и устанавливает контур ячейки на красный.

Я хочу, чтобы тот же эффект происходил, когда кто-то вводит отрицательный или нулевой вход в ячейку.Я получил это:

    @Override
    public void setValueAt(Object val, int rowIndex, int columnIndex) {
       if (val instanceof Number && ((Number) val).doubleValue() > 0) {
              super.setValueAt(val, rowIndex, columnIndex);
            } 
       }
   }

Это не позволяет ячейке принимать любые неположительные значения, но она не устанавливает красный цвет и оставляет ячейку доступной для редактирования.

Я попытался выяснить, как JTable делает отклонение по умолчанию, но, похоже, не могу его найти.

Как сделать так, чтобы он отклонял неположительный вход так же, как он отклоняет нецелочисленный ввод?

Спасибо

Ответы [ 3 ]

14 голосов
/ 24 сентября 2011

private static class JTable.GenericEditor использует самоанализ для выявления исключений, возникающих при построении определенных подклассов Number с недопустимыми значениями String.Если вам не нужно такое общее поведение, рассмотрите возможность создания PositiveIntegerCellEditor в качестве подкласса DefaultCellEditor.Ваш stopCellEditing() метод был бы соответственно более простым.

Приложение: Обновлено для использования RIGHT выравнивания и общего кода ошибки.

Приложение: См. Также Использование редактора дляПроверить введенный пользователем текст .

enter image description here

    private static class PositiveIntegerCellEditor extends DefaultCellEditor {

    private static final Border red = new LineBorder(Color.red);
    private static final Border black = new LineBorder(Color.black);
    private JTextField textField;

    public PositiveIntegerCellEditor(JTextField textField) {
        super(textField);
        this.textField = textField;
        this.textField.setHorizontalAlignment(JTextField.RIGHT);
    }

    @Override
    public boolean stopCellEditing() {
        try {
            int v = Integer.valueOf(textField.getText());
            if (v < 0) {
                throw new NumberFormatException();
            }
        } catch (NumberFormatException e) {
            textField.setBorder(red);
            return false;
        }
        return super.stopCellEditing();
    }

    @Override
    public Component getTableCellEditorComponent(JTable table,
        Object value, boolean isSelected, int row, int column) {
        textField.setBorder(black);
        return super.getTableCellEditorComponent(
            table, value, isSelected, row, column);
    }
}
2 голосов
/ 23 сентября 2011

Я понял это.Переопределите DefaultCellEditor и верните false / установите границу красного цвета, если указанное число не является положительным.

К сожалению, так как JTable.GenericEditor имеет область действия static w / default, я не могу переопределить GenericEditor, чтобы предоставить эту функцию, и мне нужно повторно реализовать ее с несколькими изменениямиесли у кого-то нет лучшего способа сделать это, о котором я хотел бы услышать.

    @SuppressWarnings("serial")
    class PositiveNumericCellEditor extends DefaultCellEditor {

        Class[] argTypes = new Class[]{String.class};
        java.lang.reflect.Constructor constructor;
        Object value;

        public PositiveNumericCellEditor() {
            super(new JTextField());
            getComponent().setName("Table.editor");
            ((JTextField)getComponent()).setHorizontalAlignment(JTextField.RIGHT);
        }

        public boolean stopCellEditing() {
            String s = (String)super.getCellEditorValue();
            if ("".equals(s)) {
                if (constructor.getDeclaringClass() == String.class) {
                    value = s;
                }
                super.stopCellEditing();
            }

            try {
                value = constructor.newInstance(new Object[]{s});
                if (value instanceof Number && ((Number) value).doubleValue() > 0)
                {
                    return super.stopCellEditing();
                } else {
                    throw new RuntimeException("Input must be a positive number."); 
                }
            }
            catch (Exception e) {
                ((JComponent)getComponent()).setBorder(new LineBorder(Color.red));
                return false;
            }
        }

        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;
                }
                constructor = type.getConstructor(argTypes);
            }
            catch (Exception e) {
                return null;
            }
            return super.getTableCellEditorComponent(table, value, isSelected, row, column);
        }

        public Object getCellEditorValue() {
            return value;
        }
    }
1 голос
/ 10 марта 2014

Этот код является небольшим улучшением принятого ответа. Если пользователь не вводит никакого значения, щелкнув по другой ячейке, позволить ему выбрать другую клетку. Принятое решение не разрешить это.

@Override
public boolean stopCellEditing() {

    String text = field.getText();

    if ("".equals(text)) {
        return super.stopCellEditing();
    }

    try {
        int v = Integer.valueOf(text);

        if (v < 0) {
            throw new NumberFormatException();
        }            
    } catch (NumberFormatException e) {

        field.setBorder(redBorder);
        return false;
    }

    return super.stopCellEditing();
}

Это решение проверяет наличие пустого текста. В случае пустого текста мы вызываем метод stopCellEditing().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...