Pregunta

Estoy usando un NumberFormatter y JFormattedTextField, pero el .getValue() no devuelve el mismo valor que el usuario está viendo.

Creo que la entrada-serie se analiza usando NumberFormats analizan método, y consigo el Numberformat de NumberFormat.getNumberInstance(); con la configuración regional real. Así que no creo que fácilmente puede extenderlo y escribir mi propio análisis sintáctico-método?

En el ejemplo , si el usuario 1234.487 la getValue() volverá: 1234.487 pero se mostrará al usuario 1,234.49

Otro ejemplo , utilizando NumberFormat.getCurrencyInstance();. El 1234.487 tipos de utilización y el getValue() volverán 1234.487 pero el usuario se mostrarán $1,234.49

En lugar , quiero una ParseException generarse si el formateador no puede formatear el valor sin redondeo. Lo mismo si el usuario escribe 4.35b6, por defecto el formateador mostrará 4.35 y se 4.35 el valor, pero quiero un ParseException, debido a que el usuario escribió en un no válido valor.

Este es el código que he tratado con:

NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
final JFormattedTextField ftf = new JFormattedTextField(nf);
ftf.setValue(new BigDecimal("1234.50"));

// Print the value from ftf
final JTextField txt = new JTextField(12);
txt.addFocusListener(new FocusAdapter() {
    public void focusGained(FocusEvent e) {
        txt.setText(ftf.getValue().toString());
    }
});

¿Cómo obtener el mismo valor que el usuario está viendo?

¿Fue útil?

Solución

Se debe extender NumberFormatter en lugar de NumberFormat y anular stringToValue para que verifica que cuando se analiza la cadena obtiene nuevamente el valor original:

class StrictNumberFormatter extends javax.swing.text.NumberFormatter {
    @Override
    public Object stringToValue(String text) throws ParseException {
        Object parsedValue = super.stringToValue(text);
        String expectedText = super.valueToString(parsedValue);
        if (! super.stringToValue(expectedText).equals(parsedValue)) {
            throw new ParseException("Rounding occurred", 0);
        }
        return parsedValue;
    }

    public StrictNumberFormatter(NumberFormat nf) {
        super(nf);
    }
}

NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
JFormattedTextField.AbstractFormatter formatter = new StrictNumberFormatter(nf);
final JFormattedTextField ftf = new JFormattedTextField(formatter);
ftf.setValue(new BigDecimal("1234.50"));

Este formateador rechace el nuevo texto si los valores antes y después de redondeo no coinciden.

Nota: esto se compara los valores , no las cuerdas. Se tolerará cambios como la eliminación de caracteres de agrupación ("$1,000" => "$1000") y ceros ("$1.20" => "$1.2"). Básicamente, si el NumberFormat devuelve el mismo valor, entonces es aceptable. Sin embargo, las restricciones impuestas por el NumberFormat todavía se aplican, por ejemplo, no se debe quitar el símbolo de moneda o insertar espacios iniciales, etc.

Otros consejos

Prueba esto:

txt.setText(ftf.getFormatter().valueToString(ftf.getValue()));

También tendrá que manejar la java.text.ParseException que el método valueToString lanza.

Editar El formateador puede ser configurado para no permitir entradas no válidas en total, lo que podría ayudar:

    ((DefaultFormatter)ftf.getFormatter()).setAllowsInvalid( false );
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top