How can I make JFormattedTextField use $1.55, but store the value as the Integer 155?
-
04-03-2021 - |
Frage
Almost everything I've ever read about Java says don't use float or double for currency, but it seems like everything in Swing tries to force you to do exactly that if you want to input / display currency values that have decimal places (aka exactly what most people want to do).
I can use NumberFormat.getCurrencyInstance()
with a NumberFormatter
and JFormattedTextField
, but I can't figure out how to get it to display decimal places without using Float
or Double
. I've got to be overlooking something simple.
How can I make my currency fields display $1.55
, accept input as 1.55
and store the input as an Integer with a value of 155
(cents)?
Lösung
You cannot do math on formatters. What you should do is have a member variable of your pojo holding the price in cents. Something like:
private long priceInDollarCents;
Then you can have a getter which will return this in dollars. Something like:
public double getPriceInDollars() {
return (double)priceInDollarCents/100;
}
This is what you'll pass into your formatter.
Andere Tipps
You can do something like this:
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);
}
}