Java: Влияет ли Locale на Formatter для JFormattedTextField - PullRequest
1 голос
/ 26 декабря 2011

Я создал пользовательский компонент (NumberFormattedTextField) из JFormattedTextField.Это форматер, который я использую:

    public static InternationalFormatter getDecimalIFormatter92() {
    // For Buy & Sale Price
    DecimalFormat numberFormat = (DecimalFormat) DecimalFormat.getNumberInstance();
    numberFormat.setMaximumFractionDigits(2);
    numberFormat.setMinimumFractionDigits(2);
    numberFormat.setRoundingMode(RoundingMode.HALF_UP);
    numberFormat.setGroupingUsed(false);

    final InternationalFormatter formatter = new InternationalFormatter(numberFormat);
    formatter.setAllowsInvalid(false);
    formatter.setMinimum(0.00);
    formatter.setMaximum(999999999.99);

    return formatter;
}

Когда я создаю экземпляр NumberFormattedTextField:

 public RelationsPanel(CashParent parent) {
    try {
    initComponents();   // startBalTxt = new NumberFormattedTextField();
    Utility.logInfo("initComponents OVER");
    myParent = parent;
    nameTxt.setSizeLimit(20);
    System.out.println("startBalTxt.setFormatter GOING FOR IT"); 
    this.startBalTxt.setFormatter(Utility.getDecimalIFormatter82());  // Must be throwing here
    System.out.println("startBalTxt.setFormatter DONE"); 
    this.currentBalTxt.setFormatter(Utility.getDecimalIFormatter82());
    } catch (Exception e) {
        Utility.logInfo("Failed to Initialize : " + e.getMessage());
        e.printStackTrace();
    }
}

NumberFormattedTextField Код CLASS:

public class NumberFormattedTextField extends JFormattedTextField implements java.io.Serializable, DocumentListener, FocusListener {
private DecimalFormat numberFormat;
private InternationalFormatter formatter;
private double MAX_VALUE = 999999.99;
private final Map attributes = (Utility.getTextFont()).getAttributes();

/**
 * Creates a NumberFormattedTextField with 6 Integer & 2 Fractional digits.
 * Minimum is set to 0.00 and Max to 999999.99 without any grouping used.
 */
public NumberFormattedTextField() {
    super();
    createFormatter();  // Creates a default formatter, used if formatter is not set
    this.setValue(0.00);
    init();
}


private void createFormatter() {
    // Create standard DecimalFormat
    numberFormat = (DecimalFormat) DecimalFormat.getNumberInstance();
    numberFormat.setMaximumFractionDigits(2);
    numberFormat.setMinimumFractionDigits(2);
    numberFormat.setRoundingMode(RoundingMode.HALF_UP);
    numberFormat.setGroupingUsed(false);

    formatter = new InternationalFormatter(numberFormat);
    formatter.setAllowsInvalid(false);
    formatter.setMinimum(0.00);
    formatter.setMaximum(999999.99);

    this.setFormatterFactory(new AbstractFormatterFactoryImpl());
}

private void init() {
    setFont(Utility.getTextFont());
    this.getDocument().addDocumentListener(this);
    this.addFocusListener(this);
    attributes.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
    setFocusLostBehavior(PERSIST);
}

public void setFormatter(InternationalFormatter format) {
    super.setFormatter(format);
    System.out.println("Class of Format = " + format.getFormat().getClass());
    if (format.getFormat() instanceof java.text.DecimalFormat)
        numberFormat = (DecimalFormat)format.getFormat();
    else
        numberFormat = (DecimalFormat)(NumberFormat) format.getFormat();

    formatter = format;
    // AbstractFormatterFactoryImpl returns formatter straight away    
    this.setFormatterFactory(new AbstractFormatterFactoryImpl());
    calculateMaxValue();
}

private void calculateMaxValue() {
    try {
        if (formatter.getMaximum() != null) {
            //System.out.println(" MAX ALlowed = " + formatter.getMaximum());
            String no = formatter.valueToString(formatter.getMaximum());
            char seperator = java.text.DecimalFormatSymbols.getInstance().getGroupingSeparator();
            no = no.replace(String.valueOf(seperator), "");
            System.out.println("MAX Number to PArse = " + no);
            MAX_VALUE = Double.parseDouble(no);  // HERE ITS THROWING EXCEPTION
        }
    } catch (ParseException ex) {
        Logger.getLogger(NumberFormattedTextField.class.getName()).log(Level.SEVERE, null, ex);
    }
}

Код вышемой компьютер работает на отличноНо на клиентском ПК выдает ошибку: Не удалось инициализировать: Для входной строки: «99999999,99» ОШИБКА / Журналы, которые я ПОЛУЧУ:

      startBalTxt.setFormatter GOING FOR IT
  INFO: initComponents OVER
  Class of Format = class java.text.DecimalFormat
  MAX Number to PArse = 99999999,99
  INFO: Failed to Initialize : For input string: "99999999,99"
  java.lang.NumberFormatException: For input string: "99999999,99"
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1241)
    at java.lang.Double.parseDouble(Double.java:540)
    at cashaccountingapp.components.NumberFormattedTextField.calculateMaxValue(NumberFormattedTextField.java:184)
 Class of Format = class java.text.DecimalFormat
    at cashaccountingapp.components.NumberFormattedTextField.setFormatter(NumberFormattedTextField.java:173)
    at cashaccountingapp.data.RelationsPanel.<init>(RelationsPanel.java:35)

Языковой стандарт для нас обоих различен.

В чем может быть причина этой ошибки?Другой язык или что-то еще, что мне нужно позаботиться в моем классе NumberFormattedTextField.Я хочу, чтобы приложение адаптировало системные настройки и показывало соответственно.

Как решить проблему ??

Ответы [ 3 ]

4 голосов
/ 26 декабря 2011

наиболее вероятно (не может быть полностью уверен, поскольку вы не показываете начальную настройку и наносите ошибку только на ее сообщение ;-) причина - разные локали: один имеет точку как десятичную точку, другой имеетзапятаяТаким образом, если вы инициализируете один строкой, представляющей число в другом, он будет конфликтовать: запятая не интерпретируется как десятичный разделитель, поэтому максимальное значение слишком велико, чтобы соответствовать ограничениям

1 голос
/ 27 декабря 2011

Получил решение:

Я получаю экземпляр Locale.US для DecimalFormatSymbols. Это помогает мне получить строку в стандартном формате с правильным десятичным разделителем. И, таким образом, я могу проанализировать действительную строку в Double. Вот код, который я изменил, если он вообще может помочь любому телу:

    private void calculateMaxValue() {
    try {
        if (formatter.getMaximum() != null) {
            String no = formatter.valueToString(formatter.getMaximum());
            // Get DecimalFormatSymbols instance of Locale.US
            char seperator = java.text.DecimalFormatSymbols.getInstance(java.util.Locale.US).getGroupingSeparator();
            no = no.replace(String.valueOf(seperator), "");
            MAX_VALUE = Double.parseDouble(no);
        }
    } catch (ParseException ex) {
        Utility.logs.log(Level.SEVERE, null, ex);
    }
}

Вот и все, никаких других изменений не требовалось.

Спасибо.

0 голосов
/ 12 января 2012

После двух часов поиска в Google и внесения некоторых изменений я получаю более простое решение - принимать только точку (.) В качестве десятичного разделителя в JFormattedTextField:

JFormattedTextField txtTax = new javax.swing.JFormattedTextField();
txtTax.setFormatterFactory(new DefaultFormatterFactory(new NumberFormatter(new DecimalFormat("#,##0.00", new DecimalFormatSymbols(new Locale("us", "EN"))))));

Это решение игнорирует System locale(ec,ES) и устанавливает для компонента конкретную локаль (us, EN)

...