Make a JFormattedTextField behave like ATM input

后端 未结 3 1159
萌比男神i
萌比男神i 2020-12-11 12:21

I would like to know if there is anyway to make a JformattedTextField or jtextField behave like an atm money input. With that I mean you enter from the right to left, say yo

3条回答
  •  天涯浪人
    2020-12-11 12:40

    Take a look at How to use Formatted Text Fields, in particular Using MaskFormatter.

    Something like...

    MaskFormatter formatter = new MaskFormatter("##.##");
    JFormattedTextField field = JFormattedTextField(formatter);
    

    for example may help.

    Simple example

    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();
                    }
                }
            });
        }        
    }
    

    Additional Example

    Now, I realise that the previous example doesn't meet your exact needs (as you described them), it is a simple solution, I've also added a DocumentFilter example...

    enter image description here

    Which will output...

    Value = 0.1
    Value = $0.10
    

    enter image description here

    Which will output

    Value = 10.0
    Value = $10.00
    

    Code...

    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);
                }
            }
        }
    }
    

    Check out DocumentFilter examples for more details

提交回复
热议问题