如何让 JFormattedTextField 使用 1.55 美元,但将值存储为整数 155?

Posted

技术标签:

【中文标题】如何让 JFormattedTextField 使用 1.55 美元,但将值存储为整数 155?【英文标题】:How can I make JFormattedTextField use $1.55, but store the value as the Integer 155? 【发布时间】:2011-11-19 09:14:43 【问题描述】:

我读过的关于 Java 的几乎所有内容都说不要使用 float 或 double 作为货币,但如果你想输入/显示具有小数的货币值,Swing 中的所有内容似乎都试图强制你这样做地方(也就是大多数人想要做的事情)。

我可以将NumberFormat.getCurrencyInstance()NumberFormatterJFormattedTextField 一起使用,但如果不使用FloatDouble,我无法弄清楚如何让它显示小数位。我必须忽略一些简单的事情。

如何让我的货币字段显示$1.55,接受输入为1.55,并将输入存储为值为155(美分)的整数?

【问题讨论】:

BigDecimal 是您精确计算货币的朋友 @kleopatra:只要你不做太多的事情,简单地使用 Java 对象就会成为瓶颈。重用您的“股票市场”论点:不知何故,我非常怀疑使用 Java BigDecimal 完成的高频交易……我很确定“整数数学”可以节省这里的一天(不太确定 Java 是否被用于高频交易;) 【参考方案1】:

您不能对格式化程序进行数学运算。您应该做的是让您的 pojo 的成员变量以美分为单位保存价格。比如:

private long priceInDollarCents;

然后你可以有一个吸气剂,它将以美元返回。比如:

public double getPriceInDollars() 
    return (double)priceInDollarCents/100;

这是您将传递给格式化程序的内容。

【讨论】:

金融界只有两位小数是不够的(参见 f.i. 证券交易所价值) @kleopatra:很可能是的。因为天体物理计算等是不够的。 @cherouvim 我猜我不需要担心来回转换为double,只要它严格用于输入/输出。更具体地说,如果我不与double 值进行任何计算或比较,是否有任何方法可以在doublelong 之间进行转换?既然大家都说不要用double作为货币,我就担心把我的值转换成double,即使只是为了编辑。 如果您可以要求用户以美分输入价格,那会更好(对于您作为程序员而言)。虽然有时这是不可接受的。用户需要输入美元,而你应该操纵美分。【参考方案2】:

你可以这样做:

CustomizedField.java

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JTextField;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;

public class CustomizedField extends JTextField

    private static final long serialVersionUID = 1L;

    public CustomizedField(int size)
    
        super(size);
        setupFilter();
    

    public int getCents()
    
        String s = getText();
        System.out.println(s);
        if(s.endsWith(".")) s = s.substring(0, s.length() - 1);
        double d = Double.parseDouble(s) * 100;
        return (int) d;
    

    private void setupFilter()
    

        ((AbstractDocument) getDocument()).setDocumentFilter(new DocumentFilter()
        

            @Override
            public void insertString(FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException
            
                check(fb, offset, text, attr);
            

            @Override
            public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attr) throws BadLocationException
            
                check(fb, offset, text, attr);
            

            private void check(FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException
            
                StringBuilder sb = new StringBuilder();
                sb.append(fb.getDocument().getText(0, fb.getDocument().getLength()));
                sb.insert(offset, text);
                if(!containsOnlyNumbers(sb.toString())) return;
                fb.insertString(offset, text, attr);
            

            private boolean containsOnlyNumbers(String text)
            
                Pattern pattern = Pattern.compile("([+-]0,1)?[\\d]*.([\\d]0,2)?");
                Matcher matcher = pattern.matcher(text);
                boolean isMatch = matcher.matches();
                return isMatch;
            

        );
    


Test.java

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

public class Test

    public static void main(String[] args)
    
        JFrame frame = new JFrame("Testing CustomizedField");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new FlowLayout());

        final CustomizedField cField = new CustomizedField(10);
        final JTextField output = new JTextField(10);
        JButton btn = new JButton("Print cents!");
        btn.addActionListener(new ActionListener()
        
            @Override
            public void actionPerformed(ActionEvent event)
            
                output.setText(cField.getCents() + " cents");
            
        );

        frame.add(cField);
        frame.add(btn);
        frame.add(output);
        frame.pack();
        frame.setVisible(true);
    

【讨论】:

以上是关于如何让 JFormattedTextField 使用 1.55 美元,但将值存储为整数 155?的主要内容,如果未能解决你的问题,请参考以下文章

Double的JFormattedTextField仍然需要字符[重复]

如何从 JformattedTextfield 检索货币格式值

获得焦点时如何选择 JFormattedTextField 中的所有文本?

具有任意小数位数的 JFormattedTextfield

如何从另一个 java 类中的 jTextField 或 jFormattedTextField 获取数据

JFormattedTextField 问题