使JFormattedTextField的行为类似于ATM输入

我想知道是否有一个JformattedTextField或jtextField表现得像一个atm money输入。 我的意思是你从右到左进入,比如说你输入10你需要再按2个0,这样它就是10.00。 程序从右到左自动输入小数点? 如果未输入2 0,则仅为.10。 这可能吗? 如果我想使用该字符串进行计算,那将如何返回给我? 我尝试了抽象格式化程序,但这样做不太好。 我想用它来输入客户收到的金额。 但要做到白痴certificate。

这会强制用户始终从右侧输入文本,无论插入符的位置如何。 插入新字符时,所有先前的字符都向左移动。 格式化将根据您的格式化程序应用:

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(…)方法返回实际数字。

看看如何使用格式化文本字段 ,特别是使用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示例以获取更多详细信息

DocumentFilter用于JTextField并覆盖适当的方法来处理数字格式。 如果您可以发布您尝试过的内容并且“不起作用”,那也很好。