如何让 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()
与NumberFormatter
和JFormattedTextField
一起使用,但如果不使用Float
或Double
,我无法弄清楚如何让它显示小数位。我必须忽略一些简单的事情。
如何让我的货币字段显示$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
值进行任何计算或比较,是否有任何方法可以在double
和long
之间进行转换?既然大家都说不要用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 中的所有文本?