Как получить то же значение, которое видит пользователь, из JFormattedTextField?

StackOverflow https://stackoverflow.com/questions/2206371

Вопрос

я использую 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 );
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top