Java 在JSpinner中显示货币

Java 在JSpinner中显示货币,java,swing,spinner,currency,jspinner,Java,Swing,Spinner,Currency,Jspinner,我为我们公司写了一个小程序,负责饮料的销售,每个用户都有自己的账户。为了增加他的帐户,有一个JSpinner,看起来像这样。一位员工问我是否可以将货币添加到此微调器。所以我实现了它,但现在您只能使用货币符号存款,而不能不使用货币符号,这让其他工作人员感到不安,所以让我们来回答我的问题,我如何才能同时接受带货币和不带货币的条目 基本微调器(如上图所示): 为了添加货币,我使用了这个代码段,它工作得很好 String pattern = "0€"; JSpinner.NumberEd

我为我们公司写了一个小程序,负责饮料的销售,每个用户都有自己的账户。为了增加他的帐户,有一个JSpinner,看起来像这样。一位员工问我是否可以将货币添加到此微调器。所以我实现了它,但现在您只能使用货币符号存款,而不能不使用货币符号,这让其他工作人员感到不安,所以让我们来回答我的问题,我如何才能同时接受带货币和不带货币的条目

基本微调器(如上图所示):

为了添加货币,我使用了这个代码段,它工作得很好

    String pattern = "0€";
    JSpinner.NumberEditor editor = new JSpinner.NumberEditor( valueSpinner, pattern );
    valueSpinner.setEditor( editor );
我已经尝试编写一个自定义JSpinner,但我无法实现微调器同时包含两个条目。

以下是关于测量长度单位的问题的答案,您可以对货币使用类似的方法:

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);
    }
}
在这段代码(第一次编辑)中,我正在解析货币ISO代码,并将其与受支持货币的
集合进行检查

注意:我已经阅读了和,但找不到任何关于指定可选货币符号的内容,因此我认为您必须使用自定义的
模式
,如本答案中前面的示例代码,我也在这里发布这些链接,以防其他人在其中找到解决方案

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);
    }
}
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);
    }
}