Как пометить ввод ячейки JTable как недопустимый?
если я JTable
и укажите тип класса столбца в его модели следующим образом:
DefaultTableModel model = new DefaultTableModel(columnNames, 100) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return Integer.class;
}};
затем, когда пользователь пытается ввести double
значение в таблицу, Swing автоматически отклоняет вход и устанавливает контур ячейки в красный цвет.
Я хочу, чтобы тот же эффект произошел, когда кто-то вводит "отрицательный или 0" вход в ячейку. У меня есть вот что:
@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 ответов
на private static class JTable.GenericEditor
использует интроспекцию, чтобы поймать исключения, вызванные конкретными строительства Number
подклассы с поврежденных String
значения. Если вам не нужно такое общее поведение, подумайте о создании PositiveIntegerCellEditor
как подкласс DefaultCellEditor
. Ваш stopCellEditing()
метод был бы соответственно проще.
добавление: обновлено для использования RIGHT
выравнивание и общий код ошибки.
добавление: см. также использование редактора для проверки Введенный Пользователем Текст.
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);
}
}
я понял. Переопределите 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;
}
}
этот код является небольшим улучшением принятого ответа. Если пользователь не вводит никакого значения, щелчок по другой ячейке должен позвольте ему выбрать другую ячейку. Принятое решение не допустить этого.
@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()
метод.