Как получить то же значение, которое видит пользователь, из JFormattedTextField?
-
18-09-2019 - |
Вопрос
я использую NumberFormatter
и JFormattedTextField
, но .getValue()
не возвращает то же значение, которое видит пользователь.
Я думаю, что входная строка анализируется с использованием метода анализа NumberFormats, и я получаю числовой формат из NumberFormat.getNumberInstance();
с фактической локалью.То есть я не думаю, что смогу легко расширить его и написать свой собственный метод синтаксического анализа?
В примере, если пользователь вводит 1234.487
тот getValue()
вернется:1234.487
но пользователь будет отображаться 1,234.49
Другой пример, с использованием NumberFormat.getCurrencyInstance();
.Пользователь вводит 1234.487
и getValue()
вернется 1234.487
но пользователь будет отображаться $1,234.49
Вместо, я хочу, чтобы было сгенерировано исключение ParseException, если форматтер не может отформатировать значение без округления.То же самое, если пользователь вводит 4.35b6
, по умолчанию форматтер отобразит 4.35
и значение будет 4.35
, но мне нужно исключение ParseException, потому что пользователь ввел неверный ценить.
Вот код, который я пробовал:
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());
}
});
Как получить то же значение, которое видит пользователь?
Решение
Вам следует продлить NumberFormatter
скорее, чем NumberFormat
и переопределить stringToValue
чтобы он проверял, что при анализе строки вы возвращаете исходное значение:
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"));
Этот форматтер отклонит новый текст, если значения до и после округления не совпадают.
Примечание:это сравнивает ценности, а не строки.Он будет терпеть такие изменения, как удаление группирующих символов ("$1,000"
=> "$1000"
) и конечные нули ("$1.20"
=> "$1.2"
).В основном, если NumberFormat
возвращает то же значение, тогда оно приемлемо.Но любые ограничения, налагаемые NumberFormat
все еще применяется, напримервы не должны удалять символ валюты или вставлять начальные пробелы и т. д.
Другие советы
Попробуй это:
txt.setText(ftf.getFormatter().valueToString(ftf.getValue()));
Вам также придется справиться с java.text.ParseException
что valueToString
метод выдает.
Редактировать:Форматер можно настроить на полное запрещение недопустимых записей, что может помочь:
((DefaultFormatter)ftf.getFormatter()).setAllowsInvalid( false );