首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在JSpinner中显示货币

在JSpinner中显示货币
EN

Stack Overflow用户
提问于 2020-01-28 18:55:51
回答 1查看 268关注 0票数 0

我为我们公司写了一个小程序,它负责饮料的销售,每个用户都有自己的账户。为了给他的账户充值,有一个看起来像这个https://i.imgur.com/qJpPfqR.png的JSpinner。一位员工问我是否可以将货币添加到这个旋转器中。所以我实现了它,但是现在你只能使用货币符号存入,而不能没有它,这让其他工作人员感到不安,所以让我们来看看我的问题,我如何才能接受有货币和没有货币的两个条目?

基本微调器(类似于我在上面发布的图像):

代码语言:javascript
复制
final SpinnerNumberModel spinnerModel = new SpinnerNumberModel( 1, 1, 1000, 1 );
final JSpinner valueSpinner = new JSpinner( spinnerModel );

为了添加货币,我使用了下面的代码片段,它工作得很好

代码语言:javascript
复制
    String pattern = "0€";
    JSpinner.NumberEditor editor = new JSpinner.NumberEditor( valueSpinner, pattern );
    valueSpinner.setEditor( editor );

我已经尝试过编写一个自定义的JSpinner,但我无法实现微调器同时接受这两个条目。

EN

回答 1

Stack Overflow用户

发布于 2020-01-28 20:38:35

this回答了一个关于长度单位的问题后,你可以用类似的方法来测量货币:

代码语言:javascript
复制
import java.text.ParseException;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFormattedTextField.AbstractFormatter;
import javax.swing.JFormattedTextField.AbstractFormatterFactory;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JSpinner.DefaultEditor;
import javax.swing.SpinnerNumberModel;

public class MainWithFormatter {

    //For more currencies and their ISO codes, visit https://en.wikipedia.org/wiki/List_of_circulating_currencies
    public static enum Currency {
        EUR, //Euro
        USD, //United States Dollar
        GBP, //British Pound
        JPY //Japanese Yen
    }

    public static class CurrencyFormatter extends AbstractFormatter {

        private static final Pattern PATTERN;

        static {
            //Building the Pattern is not too tricky. It just needs some attention.

            final String blank = "\\p{Blank}"; //Match any whitespace character.
            final String blankGroupAny = "(" + blank + "*)"; //Match any whitespace character, zero or more times and group them.

            final String digits = "\\d"; //Match any digit.
            final String digitsGroup = "(" + digits + "+)"; //Match any digit, at least once and group them.
            final String digitsSuperGroup = "(\\-?" + digitsGroup + "\\.?" + digitsGroup + "?)"; //Matches for example "-2.4" or "2.4" or "2" or "-2" in the same group!

            //Create the pattern part which matches any of the available currencies...
            final Currency[] currencies = Currency.values();
            final StringBuilder currenciesBuilder = new StringBuilder(Pattern.quote("")); //Empty currency value is valid.
            for (int i = 0; i < currencies.length; ++i)
                currenciesBuilder.append('|').append(Pattern.quote(currencies[i].name()));
            final String currenciessGroup = "(" + currenciesBuilder + ")";

            final String full = "^" + blankGroupAny + digitsSuperGroup + blankGroupAny + currenciessGroup + blankGroupAny + "$"; //Compose full pattern.

            PATTERN = Pattern.compile(full);
        }

        private final Currency defaultCurrency;
        private Currency lastCurrency;
        private boolean verbose; //Show the default currency while spinning or not?

        public CurrencyFormatter(final Currency defaultCurrency) {
            this.defaultCurrency = Objects.requireNonNull(defaultCurrency);
            lastCurrency = defaultCurrency;
            verbose = true;
        }

        @Override
        public Object stringToValue(final String text) throws ParseException {
            if (text == null || text.trim().isEmpty())
                throw new ParseException("Null or empty text.", 0);
            try {
                final Matcher matcher = PATTERN.matcher(text.toUpperCase());
                if (!matcher.matches())
                    throw new ParseException("Invalid input.", 0);
                final String amountStr = matcher.group(2),
                             currencyStr = matcher.group(6);
                final double amount = Double.parseDouble(amountStr);
                if (currencyStr.trim().isEmpty()) {
                    lastCurrency = defaultCurrency;
                    verbose = false;
                }
                else {
                    lastCurrency = Currency.valueOf(currencyStr);
                    verbose = true;
                }
                return amount;
            }
            catch (final IllegalArgumentException iax) {
                throw new ParseException("Failed to parse input \"" + text + "\".", 0);
            }
        }

        public Currency getLastCurrency() {
            return lastCurrency;
        }

        @Override
        public String valueToString(final Object value) throws ParseException {
            final String amount = String.format("%.2f", value).replace(',', '.');
            return verbose ? (amount + ' ' + lastCurrency.name()) : amount;
        }
    }

    public static class CurrencyFormatterFactory extends AbstractFormatterFactory {
        @Override
        public AbstractFormatter getFormatter(final JFormattedTextField tf) {
            if (!(tf.getFormatter() instanceof CurrencyFormatter))
                return new CurrencyFormatter(Currency.USD);
            return tf.getFormatter();
        }
    }

    public static void main(final String[] args) {
        final JSpinner spin = new JSpinner(new SpinnerNumberModel(0d, -1000000d, 1000000d, 0.01d));

        final JFormattedTextField jftf = ((DefaultEditor) spin.getEditor()).getTextField();
        jftf.setFormatterFactory(new CurrencyFormatterFactory());

        //Added a button to demonstrate how to obtain the value the user has selected:
        final JButton check = new JButton("Check!");
        check.addActionListener(e -> {
            final CurrencyFormatter cf = (CurrencyFormatter) jftf.getFormatter();
            JOptionPane.showMessageDialog(check, Objects.toString(spin.getValue()) + ' ' + cf.getLastCurrency().name() + '!');
        });

        final JPanel contents = new JPanel(); //FlowLayout.
        contents.add(spin);
        contents.add(check);

        final JFrame frame = new JFrame("JSpinner currencies.");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(contents);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

您只需要为处理此类字符串的微调器的默认编辑器的格式化文本字段创建一个自定义AbstractFormatter

尽管您可以简单地放入两个JSpinner,一个用于金额,另一个用于货币。

编辑1:或者,您可以使用内置的java.util.Currency类:

代码语言:javascript
复制
import java.text.ParseException;
import java.util.Currency;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFormattedTextField.AbstractFormatter;
import javax.swing.JFormattedTextField.AbstractFormatterFactory;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JSpinner.DefaultEditor;
import javax.swing.SpinnerNumberModel;

public class MainWithCurrency {

    public static class CurrencyFormatter extends AbstractFormatter {

        private static final Pattern PATTERN;

        static {
            //Building the Pattern is not too tricky. It just needs some attention.

            final String blank = "\\p{Blank}"; //Match any whitespace character.
            final String blankGroupAny = "(" + blank + "*)"; //Match any whitespace character, zero or more times and group them.

            final String digits = "\\d"; //Match any digit.
            final String digitsGroup = "(" + digits + "+)"; //Match any digit, at least once and group them.
            final String digitsSuperGroup = "(\\-?" + digitsGroup + "\\.?" + digitsGroup + "?)"; //Matches for example "-2.4" or "2.4" or "2" or "-2" in the same group!

            //Create the pattern part which matches any of the available currencies...
            final String currencyCodes = "[A-Z]{3}|" + Pattern.quote(""); //Currency code consists of 3 letters, or is empty for default value.
            final String currenciessGroup = "(" + currencyCodes + ")";

            final String full = "^" + blankGroupAny + digitsSuperGroup + blankGroupAny + currenciessGroup + blankGroupAny + "$"; //Compose full pattern.

            PATTERN = Pattern.compile(full);
        }

        private final Set<String> supportedCurrencies;
        private final String defaultCurrency;
        private String lastCurrency;
        private boolean verbose; //Show the default currency while spinning or not?

        public CurrencyFormatter(final Set<Currency> supportedCurrencies,
                                 final Currency defaultCurrency) {
            if (!supportedCurrencies.contains(defaultCurrency))
                throw new IllegalArgumentException("Default currency is not supported.");
            this.supportedCurrencies = supportedCurrencies.stream().map(currency -> currency.getCurrencyCode()).collect(Collectors.toSet());
            this.defaultCurrency = defaultCurrency.getCurrencyCode();
            lastCurrency = this.defaultCurrency;
            verbose = true;
        }

        @Override
        public Object stringToValue(final String text) throws ParseException {
            if (text == null || text.trim().isEmpty())
                throw new ParseException("Null or empty text.", 0);
            try {
                final Matcher matcher = PATTERN.matcher(text.toUpperCase());
                if (!matcher.matches())
                    throw new ParseException("Invalid input.", 0);
                final String amountStr = matcher.group(2).trim(),
                             currencyStr = matcher.group(6).trim();
                final double amount = Double.parseDouble(amountStr);
                if (currencyStr.isEmpty()) {
                    lastCurrency = defaultCurrency;
                    verbose = false;
                }
                else {
                    if (!supportedCurrencies.contains(currencyStr))
                        throw new ParseException("Unsupported currency.", 0);
                    lastCurrency = currencyStr;
                    verbose = true;
                }
                return amount;
            }
            catch (final IllegalArgumentException iax) {
                throw new ParseException("Failed to parse input \"" + text + "\".", 0);
            }
        }

        public Currency getLastCurrency() {
            return Currency.getInstance(lastCurrency);
        }

        @Override
        public String valueToString(final Object value) throws ParseException {
            final String amount = String.format("%.2f", value).replace(',', '.');
            return verbose ? (amount + ' ' + lastCurrency) : amount;
        }
    }

    public static class CurrencyFormatterFactory extends AbstractFormatterFactory {
        @Override
        public AbstractFormatter getFormatter(final JFormattedTextField tf) {
            if (!(tf.getFormatter() instanceof CurrencyFormatter))
                return new CurrencyFormatter(Currency.getAvailableCurrencies(), Currency.getInstance("USD"));
            return tf.getFormatter();
        }
    }

    public static void main(final String[] args) {
        final JSpinner spin = new JSpinner(new SpinnerNumberModel(0d, -1000000d, 1000000d, 0.01d));

        final JFormattedTextField jftf = ((DefaultEditor) spin.getEditor()).getTextField();
        jftf.setFormatterFactory(new CurrencyFormatterFactory());

        //Added a button to demonstrate how to obtain the value the user has selected:
        final JButton check = new JButton("Check!");
        check.addActionListener(e -> {
            final CurrencyFormatter cf = (CurrencyFormatter) jftf.getFormatter();
            JOptionPane.showMessageDialog(check, Objects.toString(spin.getValue()) + ' ' + cf.getLastCurrency().getCurrencyCode() + '!');
        });

        final JPanel contents = new JPanel(); //FlowLayout.
        contents.add(spin);
        contents.add(check);

        final JFrame frame = new JFrame("JSpinner currencies.");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(contents);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

在这段代码(第一次编辑)中,我解析了货币ISO代码,并对照支持的货币的Set进行了检查。

注释:我已经阅读了DecimalFormat documentationcorresponding Java Tutorial,但是找不到任何关于指定可选货币符号的内容,所以这就是为什么我认为您必须使用自定义的Pattern,就像这个答案中前面的示例代码一样,我也在这里发布了这些链接,以防其他人在其中找到解决方案。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59947168

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档