Come ottenere lo stesso valore come l'utente sta vedendo da un JFormattedTextField?
-
18-09-2019 - |
Domanda
Io sto usando un NumberFormatter
e JFormattedTextField
, ma il .getValue()
non restituisce lo stesso valore come l'utente sta vedendo.
Credo che l'ingresso-stringa viene analizzata utilizzando NumberFormats analizzare metodo, e ottengo il Numberformat dal NumberFormat.getNumberInstance();
alla locale vero e proprio. Quindi non credo che facilmente può allungare e scrivere il mio parse-metodo?
Nell'esempio , se l'utente 1234.487
il getValue()
restituirà:
1234.487
ma verrà visualizzato all'utente 1,234.49
Un altro esempio , utilizzando NumberFormat.getCurrencyInstance();
. L'utente digita 1234.487
e la getValue()
torneranno 1234.487
ma l'utente sarà visualizzata $1,234.49
Invece , voglio una ParseException essere generato se il Formatter non può formattare il valore senza arrotondamento. Stessa cosa se l'utente digita 4.35b6
, per impostazione predefinita il formattatore visualizzerà 4.35
e il valore verrà 4.35
, ma voglio ParseException, perché l'utente ha digitato in un non valida Valore.
Ecco il codice che ho provato 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());
}
});
Come ottenere lo stesso valore come l'utente sta vedendo?
Soluzione
Si dovrebbe estendere NumberFormatter
piuttosto che NumberFormat
e sovrascrivere stringToValue
in modo che verifica che quando viene analizzato la corda si ottiene indietro il valore originale:
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"));
Questa formattatore rifiuterà il nuovo testo se i valori prima e dopo l'arrotondamento non corrispondono.
Nota: questo mette a confronto i Valori , non le corde. Si tollera variazioni come rimuovere caratteri di raggruppamento ("$1,000"
=> "$1000"
) e gli zeri ("$1.20"
=> "$1.2"
). In sostanza se l'NumberFormat
restituisce lo stesso valore, allora è accettabile. Ma le restrizioni imposte dal NumberFormat
ancora valide, per esempio Non è necessario rimuovere il simbolo di valuta o inserire spazi iniziali, ecc.
Altri suggerimenti
Prova questo:
txt.setText(ftf.getFormatter().valueToString(ftf.getValue()));
Avrete anche per gestire il java.text.ParseException
che il metodo valueToString
getta.
Modifica Il formattatore può essere impostato per non consentire voci non valide del tutto, che potrebbe aiutare:
((DefaultFormatter)ftf.getFormatter()).setAllowsInvalid( false );