Pergunta

Eu estou usando um NumberFormatter e JFormattedTextField, mas o .getValue() não retorna o mesmo valor que o usuário está vendo.

Eu acho que o input-string é analisado usando NumberFormats parse-método, e tenho a Numberformat de NumberFormat.getNumberInstance(); com a localidade real. Então eu não acho que facilmente pode estendê-lo e escrever a minha própria análise do método?

No exemplo , se o usuário digitar 1234.487 o getValue() retornará: 1234.487 mas o usuário será exibido 1,234.49

Outro exemplo , usando NumberFormat.getCurrencyInstance();. O 1234.487 tipos de usuário ea getValue() voltará 1234.487 mas o usuário será exibido $1,234.49

Em vez disso , eu quero um ParseException ser gerado se o Formatter não pode formatar o valor sem arredondamento. A mesma coisa se o 4.35b6 tipos de usuários, por padrão, o formatador irá exibir 4.35 eo valor será 4.35, mas eu quero uma ParseException, porque o usuário digitou um inválido valor.

Aqui está o código que eu tentei com:

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());
    }
});

Como obter o mesmo valor que o usuário está vendo?

Foi útil?

Solução

Você deve se estender NumberFormatter em vez de NumberFormat e override stringToValue para que ele verifica que quando a corda é analisado você recebe de volta o 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"));

Esta formatador vai rejeitar o novo texto se os valores antes e depois de arredondamento não coincidem.

Nota: este compara os valores , e não as cordas. Vai tolerar alterações como a remoção de caracteres de agrupamento ("$1,000" => "$1000") e zeros à direita ("$1.20" => "$1.2"). Basicamente, se o NumberFormat retorna o mesmo valor, então é aceitável. Mas quaisquer restrições impostas pelo NumberFormat ainda se aplicam, por exemplo, Você não deve remover o símbolo de moeda ou inserção principais espaços etc.

Outras dicas

Tente isto:

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

Você também terá que lidar com a java.text.ParseException que o método valueToString joga.

Editar: O formatador pode ser configurado para não permitir entradas inválidas por completo, o que pode ajudar:

    ((DefaultFormatter)ftf.getFormatter()).setAllowsInvalid( false );
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top