java - texto - ¿Cómo marcar la entrada de la celda JTable como inválida?
metodo getrowcount() java (3)
Si tomo una JTable
y especifico el classtype de una columna en su modelo de la siguiente manera:
DefaultTableModel model = new DefaultTableModel(columnNames, 100) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return Integer.class;
}};
Entonces, cada vez que un usuario intenta ingresar un valor double
en la tabla, Swing rechaza automáticamente la entrada y establece el contorno de la celda en rojo.
Quiero que ocurra el mismo efecto cuando alguien ingresa una entrada ''negativa o 0'' a la celda. Tengo esto:
@Override
public void setValueAt(Object val, int rowIndex, int columnIndex) {
if (val instanceof Number && ((Number) val).doubleValue() > 0) {
super.setValueAt(val, rowIndex, columnIndex);
}
}
}
Esto evita que la celda acepte valores no positivos, pero no establece el color en rojo y deja la celda como editable.
Traté de ver cómo JTable está haciendo el rechazo por defecto, pero parece que no puedo encontrarlo.
¿Cómo puedo hacer que rechace la entrada no positiva de la misma manera que rechaza la entrada no entera?
Gracias
Este código es una pequeña mejora de la respuesta aceptada. Si el usuario no ingresa ningún valor, al hacer clic en otra celda debería permitirle seleccionar otra celda. La solución aceptada no permite esto.
@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();
}
Esta solución busca texto vacío. En el caso de un texto vacío, llamamos al método stopCellEditing()
.
La private static class JTable.GenericEditor
utiliza la introspección para detectar las excepciones planteadas al construir subclases Number
específicas con valores de String
inválidos. Si no necesita dicho comportamiento genérico, considere la posibilidad de crear PositiveIntegerCellEditor
como una subclase de DefaultCellEditor
. Su método stopCellEditing()
sería, en consecuencia, más simple.
Addendum: actualizado para usar la alineación RIGHT
y el código de error común.
Adición: Vea también Usar un editor para validar el texto ingresado por el usuario .
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);
}
}
Me lo imaginé. Anule DefaultCellEditor y devuelva false
/ establezca el borde en rojo si el número proporcionado no es positivo.
Desafortunadamente, como JTable.GenericEditor es static
con default
alcance default
, no puedo anular el GenericEditor
para proporcionar esta funcionalidad y tener que volver a implementarla con algunos ajustes, a menos que alguien tenga una mejor manera de hacerlo, lo cual Me gustaría escuchar.
@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;
}
}