我想知道是否有任何方式使JformattedTextField或jtextField表现得像atm money输入。我的意思是你从右到左输入,比如你输入10你需要再按2个0,这样它就是10.00。程序从右到左自动输入小数点?如果未输入2 0,则仅为.10。这可能吗?如果我想使用该字符串进行计算,那将如何返回给我?我尝试了抽象格式化程序,但这并不能很好地工作。我想用它来输入客户收到的金额。但要做到白痴证明。
答案 0 :(得分:4)
这会强制用户始终从右侧输入文本,无论插入符号位于何处。插入新字符时,所有先前的字符都向左移动。格式化将根据您的格式化程序应用:
import java.awt.*;
import java.text.*;
import javax.swing.*;
import javax.swing.text.*;
public class ABMTextField extends JTextField
{
private DecimalFormat format;
private String decimal;
public ABMTextField(DecimalFormat format)
{
this.format = format;
decimal = Character.toString( format.getDecimalFormatSymbols().getDecimalSeparator() );
setColumns( format.toPattern().length() );
setHorizontalAlignment(JFormattedTextField.TRAILING);
setText( format.format(0.0) );
AbstractDocument doc = (AbstractDocument)getDocument();
doc.setDocumentFilter( new ABMFilter() );
}
@Override
public void setText(String text)
{
Number number = format.parse(text, new ParsePosition(0));
if (number != null)
super.setText( text );
}
public class ABMFilter extends DocumentFilter
{
public void insertString(FilterBypass fb, int offs, String str, AttributeSet a)
throws BadLocationException
{
replace(fb, offs, 0, str, a);
}
public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a)
throws BadLocationException
{
if ("0123456789".contains(str))
{
Document doc = fb.getDocument();
StringBuilder sb = new StringBuilder( doc.getText(0, doc.getLength()) );
int decimalOffset = sb.indexOf( decimal );
if (decimalOffset != -1)
{
sb.deleteCharAt(decimalOffset);
sb.insert(decimalOffset + 1, decimal);
}
sb.append(str);
try
{
String text = format.format( format.parse( sb.toString() ) );
super.replace(fb, 0, doc.getLength(), text, a);
}
catch(ParseException e) {}
}
else
Toolkit.getDefaultToolkit().beep();
}
public void remove(DocumentFilter.FilterBypass fb, int offset, int length)
throws BadLocationException
{
Document doc = fb.getDocument();
StringBuilder sb = new StringBuilder( doc.getText(0, doc.getLength()) );
int decimalOffset = sb.indexOf( decimal );
if (decimalOffset != -1)
{
sb.deleteCharAt(decimalOffset);
sb.insert(decimalOffset - 1, decimal);
}
sb.deleteCharAt( sb.length() - 1) ;
try
{
String text = format.format( format.parse( sb.toString() ) );
super.replace(fb, 0, doc.getLength(), text, null);
}
catch(ParseException e) {}
}
}
private static void createAndShowUI()
{
DecimalFormat format = new DecimalFormat("###,##0.00");
ABMTextField abm = new ABMTextField( format );
JPanel panel = new JPanel();
panel.add( abm );
JFrame frame = new JFrame("ABMTextField");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( panel );
frame.setSize(200, 200);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
如果我想使用该字符串进行计算,那将如何返回给我?
您需要创建一个方法,可能是getValue(),它将使用format.parse(...)方法返回实际数字。
答案 1 :(得分:2)
请查看How to use Formatted Text Fields,特别是Using MaskFormatter。
像...一样的东西。
MaskFormatter formatter = new MaskFormatter("##.##");
JFormattedTextField field = JFormattedTextField(formatter);
例如,可能有帮助。
简单示例
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.text.ParseException;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.DefaultFormatterFactory;
import javax.swing.text.MaskFormatter;
public class TestFormattedTextField {
public static void main(String[] args) {
new TestFormattedTextField();
}
public TestFormattedTextField() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
try {
JFormattedTextField field = new JFormattedTextField();
MaskFormatter formatter = new MaskFormatter("##.##");
formatter.setPlaceholderCharacter('0');
field.setFormatterFactory(new DefaultFormatterFactory(formatter));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(field);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (ParseException exp) {
exp.printStackTrace();
}
}
});
}
}
附加示例
现在,我意识到上一个示例不符合您的确切需求(正如您所描述的那样),这是一个简单的解决方案,我还添加了一个DocumentFilter
示例......
将输出...
Value = 0.1
Value = $0.10
将输出
Value = 10.0
Value = $10.00
...代码
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import java.text.ParseException;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.MaskFormatter;
public class TestFormattedTextField {
public static void main(String[] args) {
new TestFormattedTextField();
}
public TestFormattedTextField() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
MoneyField field = new MoneyField();
field.addActionListener(new ActionListener() {
@Override
@SuppressWarnings("empty-statement")
public void actionPerformed(ActionEvent e) {
MoneyField field = (MoneyField) e.getSource();
double value = field.getValue();
System.out.println("Value = " + value);
System.out.println("Value = " + NumberFormat.getCurrencyInstance().format(value));
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(field);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MoneyField extends JTextField {
public MoneyField() {
setColumns(5);
setHorizontalAlignment(RIGHT);
((AbstractDocument) getDocument()).setDocumentFilter(new Filter());
}
public double getValue() {
String text = getText();
if (!text.contains(".")) {
text = "0." + text;
}
return Double.parseDouble(text);
}
protected class Filter extends DocumentFilter {
protected String getNumbers(String text) {
StringBuilder sb = new StringBuilder(text.length());
for (char c : text.toCharArray()) {
if (Character.isDigit(c)) {
sb.append(c);
}
}
return sb.toString();
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
if (length > 0) {
fb.remove(offset, length);
}
insertString(fb, offset, text, attrs);
}
@Override
public void insertString(FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {
text = getNumbers(text);
if (text.length() > 0) {
int docLength = fb.getDocument().getLength();
if (docLength == 2) {
text = "." + text;
}
if (docLength + text.length() < 6) {
super.insertString(fb, offset, text, attr);
}
}
}
@Override
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
if (offset == 3) {
offset = 2;
length = 2;
}
super.remove(fb, offset, length);
}
}
}
}
查看DocumentFilter examples了解详情
答案 2 :(得分:1)
对JTextField使用DocumentFilter
并覆盖适当的方法来处理数字格式。如果你能发布你所尝试过的并且“不起作用”,那也很好。