有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

用于inputfield的java Sencha GXT自定义货币格式

我目前正在从事一个GWT项目,我们使用Sencha GXT libs。我目前正在尝试创建一个自定义货币格式的CurrencyField。我希望自定义货币格式的一些示例:

€ 123,45
€ 98.765.432,10
€ 400,00

所以,正如你所看到的,我想要一个前缀欧元符号;货币符号和小数点之间的空格;千分之点;逗号表示小数(当然,逗号后面还有两个小数)

然而,在GXT中,似乎无法创建自己的自定义格式我知道用常规的java.text.NumberFormat我可以做这样的事情:

NumberFormat format = NumberFormat.getCurrencyInstance();
DecimalFormatSymbols formatSymbols = new DecimalFormatSymbols();
formatSymbols.setCurrencySymbol("€");
formatSymbols.setGroupingSeparator('.');
formatSymbols.setMonetaryDecimalSeparator(',');
((DecimalFormat)format).setDecimalFormatSymbols(formatSymbols);

然而,在GXT中,com.google.gwt.i18n.client.NumberFormat必须用于NumberField<BigDecimal>setFormat-方法。我知道一些定制可以用于CurrencyData,如下所示:

private CurrencyData createCurrencyData() {
  // CurrencyData docs: http://www.gwtproject.org/javadoc/latest/com/google/gwt/i18n/client/CurrencyData.html
  return new CurrencyData() {

    @Override
    public String getCurrencySymbol() {
      return "€";
    }

    @Override
    public String getSimpleCurrencySymbol() {
      return "€";
    }

    @Override
    public String getPortableCurrencySymbol() {
      return "€";
    }

    @Override
    public String getCurrencyCode() {
      return "EUR"; // ISO4217 for this currency
    }

    @Override
    public int getDefaultFractionDigits() {
      return 2; // Amount of decimal positions
    }

    @Override
    public boolean isSymbolPrefix() {
      return true; // true to place currency symbol before the decimal
    }

    @Override
    public boolean isSymbolPositionFixed() {
      return true; // true to use the same currency symbol position regardless of locale (determined by the isSymbolPrefix-method)
    }

    @Override
    public boolean isSpacingFixed() {
      return true; // true to put a space between the currency symbol and the decimal
    }

    @Override
    public boolean isSpaceForced() {
      return true; // true to use the same spacing regardless of locale (determined by the isSpacingFixed-method)
    }

    @Override
    public boolean isDeprecated() {
      return false;
    }
  };
}

我现在是这样使用的:

NumberField<BigDecimal> currencyField = new NumberField<BigDecimal>(
  new NumberPropertyEditor.BigDecimalPropertyEditor());
currencyField.setFormat(NumberFormat.getCurrencyFormat(createCurrencyData()));

然而,有两个问题:

  1. 它没有完全定制我想要的方式。它现在接受如下输入:€123,456.78;而不是€ 123.456,78(同样,尽管CurrencyData#isSpacingForced显然应该用于货币符号和十进制之间的空格,但它对NumberField不起作用。)
  2. 当我只是键入一个像400这样的常规数字时,它会给出一个错误,而不是自动格式化用户输入:400 does not have either positive or negative affixes is not a valid number

共 (1) 个答案

  1. # 1 楼答案

    我们所做的改变:

    现在,我们将荷兰语区域设置放在.gwt.xml文件中:

    <extend-property name="locale" values="nl_NL"/>
    <set-property name="locale" value="nl_NL"/>
    <set-property-fallback name="locale" value="nl_NL"/>
    

    我们使用如下自定义格式:

    final BigDecimalField currencyField = new BigDecimalField();
    currencyField.setFormat(CustomNumberFormat.getCurrencyFormat());
    

    使用CustomNumberFormat类,如下所示:

    import java.util.Map;
    
    import com.google.gwt.core.client.GWT;
    import com.google.gwt.i18n.client.CurrencyData;
    import com.google.gwt.i18n.client.CurrencyList;
    import com.google.gwt.i18n.client.NumberFormat;
    import com.google.gwt.i18n.client.constants.CurrencyCodeMapConstants;
    
    public class CustomNumberFormat extends NumberFormat {
    
      private static CurrencyCodeMapConstants currencyCodeMapConstants = GWT.create(CurrencyCodeMapConstants.class);
      private static char currencySymbol;
      private static NumberFormat cachedCurrencyFormat;
    
      /**
       * Get the default currency format
       * @return the default currency format
       */
      public static NumberFormat getCurrencyFormat() {
        if (cachedCurrencyFormat == null) {
          cachedCurrencyFormat = getCurrencyFormat(CurrencyList.get().getDefault().getCurrencyCode());
        }
        return cachedCurrencyFormat;
      }
    
      /**
       * Get the currency format
       * @param currencyCode the code to use
       * @return the {@link NumberFormat} to use
       */
      public static NumberFormat getCurrencyFormat(final String currencyCode) {
        return new CustomNumberFormat(defaultNumberConstants.currencyPattern(), lookupCurrency(currencyCode), false, true);
      }
    
      /**
       * Lookup the currency data
       * @param currencyCode the currency code e.g. EUR
       * @return the {@link CurrencyData}
       */
      private static CurrencyData lookupCurrency(final String currencyCode) {
        final CurrencyData currencyData = CurrencyList.get().lookup(currencyCode);
    
        final Map<String, String> currencyMap = currencyCodeMapConstants.currencyMap();
    
        final String code = currencyData.getCurrencyCode();
        final String symbol = currencyMap.get(currencyCode);
        final int fractionDigits = currencyData.getDefaultFractionDigits();
        final String portableSymbol = currencyData.getPortableCurrencySymbol();
        return toCurrencyData(code, symbol, fractionDigits, portableSymbol);
      }
    
      /**
       *
       * @param code the currency code e.g. EUR
       * @param symbol the currency symbol e.g. the euro sign
       * @param fractionDigits the number of fraction digits
       * @param portableSymbol the portable symbol
       * @return the {@link CurrencyData} to use
       */
      public static native CurrencyData toCurrencyData(String code, String symbol, int fractionDigits,
          String portableSymbol) /*-{
                                 //CHECKSTYLE:OFF
                                 return [ code, symbol, fractionDigits, portableSymbol ];
                                 //CHECKSTYLE:ON
                                 }-*/;
    
      private boolean currencyFormat = false;
    
      /**
       *
       * @param pattern the currency pattern
       * @param cdata the {@link CurrencyData}
       * @param userSuppliedPattern <code>true</code> if the pattern is supplied by the user
       */
      protected CustomNumberFormat(final String pattern, final CurrencyData cdata, final boolean userSuppliedPattern,
          final boolean currencyFormat) {
        super(pattern, cdata, userSuppliedPattern);
        this.currencyFormat = currencyFormat;
      }
    
      /* (non-Javadoc)
       * @see com.google.gwt.i18n.client.NumberFormat#format(boolean, java.lang.StringBuilder, int)
       */
      @Override
      protected void format(final boolean isNegative, final StringBuilder digits, final int scale) {
        super.format(isNegative, digits, scale);
        if (this.currencyFormat) {
          final char decimalSeparator = defaultNumberConstants.monetarySeparator().charAt(0);
          if (digits.toString().endsWith(decimalSeparator + "00")) {
            digits.delete(digits.length() - 3, digits.length());
          }
          if (isNegative) {
            digits.delete(digits.length() - 1, digits.length()); // Delete leading "-"
            digits.insert(0, "- "); // Insert "- " at the front
          }
        }
      }
    
      /**
       * Parse a String. The String does not start with the expected prefix so we add it first
       * @param text the text to parse
       * @param inOutPos an offset telling us
       * @return the parsed value
       * @throws NumberFormatException if the text cannot be parsed
       */
      @Override
      public double parse(final String text, final int[] inOutPos) throws NumberFormatException {
        //add the positive prefix (euro-sign plus space)
        final String temp = getPositivePrefix() + text;
        //parse the adjusted string
        final double val = super.parse(temp, inOutPos);
        //now here is the tricky bit... during parsing the inOutPos offset was updated based on the modified String
        //but a check is maded to see if the resulting offset is equal to the length of the String we have been passed
        //so we need to update inOutPos by removing the length of the positive prefix
        inOutPos[0] -= getPositivePrefix().length();
        return val;
      }
    }
    

    现在我们得到以下结果:

    € 123,45                      when entering 123,45
    € 98.765.432,10               when entering 98765432,1
    - € 400,00                    when entering -400