【问题标题】:JFormattedTextField with a maskFormatter throws NumberFormatException带有 maskFormatter 的 JFormattedTextField 抛出 NumberFormatException
【发布时间】:2013-01-22 01:37:52
【问题描述】:

我有一个使用以下掩码格式化程序的 JFormattedTextField:

    private MaskFormatter maskForInput;
    maskForInput=new MaskFormatter("####"); // I have tried using stars (*) too.
    maskForInput.setValidCharacters("0123456789");

    javax.swing.JFormattedTextField playerRaiseField=new javax.swing.JFormattedTextField(maskForInput);

这应该允许用户输入最多 4 位数字作为输入。但是,当我尝试从该字段返回 Integer.parseInt(playerRaiseField.getText()) String 时,我总是得到 NumberFormatException 可能是由于用户输入上留下的空白空间。 要清除它:

如果用户输入560,例如有一个尾随空格,所以我正在阅读的字符串是560( ),并且当试图将这个String解析为int时,会抛出这个异常。任何解决方法?如何修改掩码格式化程序以接受 1 到 4 位数字并且总是固定 4 位数字??

注意:奇怪的是,在返回的 String 上使用 trim() 仍然不会删除多余的空白字符...

【问题讨论】:

标签: java swing parsing input integer


【解决方案1】:

您的期望有很多问题...

首先,您似乎相信格式化字段可以包含任意数量的字符。这不是真的(虽然您可以获得文本,但该字段仍处于它认为无效的状态)。格式化字段要求掩码的所有地方都必须填写。

其次,您应该使用JFormattedTextField#getValue 方法来返回字段的值,而不是getText

第三,返回的文本用掩码的占位符(MaskFormatter#getPlaceholder)填充,它可能是也可能不是空格,所以String#trim可能不会有帮助......

如果您希望用户只能输入一个可能由 0-n 个字符组成的数值,那么您确实应该考虑将DocumentFilter 应用于普通JTextField

public class TestField {

    public static void main(String[] args) {
        new TestField();
    }

    public TestField() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class NumericDocumentFilter extends DocumentFilter {

        private int maxChars;

        public NumericDocumentFilter(int maxChars) {
            this.maxChars = maxChars;
        }

        @Override
        public void insertString(DocumentFilter.FilterBypass fb, int offset,
                String text, AttributeSet attr)
                throws BadLocationException {

            StringBuilder buffer = new StringBuilder(text);
            for (int i = buffer.length() - 1; i >= 0; i--) {
                char ch = buffer.charAt(i);
                if (!Character.isDigit(ch)) {
                    buffer.deleteCharAt(i);
                }
            }

            text = buffer.toString();
            if (fb.getDocument().getLength() + text.length() > maxChars) {
                int remaining = maxChars - fb.getDocument().getLength();
                text = text.substring(0, remaining);
            }

            if (text.length() > 0) {
                super.insertString(fb, offset, text, attr);
            }
        }

        @Override
        public void replace(DocumentFilter.FilterBypass fb,
                int offset, int length, String string, AttributeSet attr) throws BadLocationException {
            if (length > 0) {
                fb.remove(offset, length);
            }
            insertString(fb, offset, string, attr);
        }
    }

    public class TestPane extends JPanel {

        private JTextField field;

        public TestPane() {

            setLayout(new GridBagLayout());

            field = new JTextField(4);
            ((AbstractDocument) field.getDocument()).setDocumentFilter(new NumericDocumentFilter(4));
            add(field);
            field.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.println(field.getText());
                }
            });
        }
    }
}

【讨论】:

    【解决方案2】:

    由于我不确定您如何使用修剪,我建议您尝试以下代码行来删除空格: 正如所讨论的,下面的代码应该可以工作:

    String playerBet=playerRaiseField.getText();
    // if playerBet is not null
    String playerBetWithoutSpaces=playerBet.trim();
    
    Integer.parseInt(playerBetWithoutSpaces);
    

    【讨论】:

    • 不是这样的,我先将getText()返回的值存储到一个String中,在这个String上使用.trim()。这可能不会有任何改变,但感谢您的帮助。
    • String playerBet=playerRaiseField.getText(); 然后playerBet.trim();
    • 然后你传递给 Integer.parseInt 什么?只是 playerBet ,如果是的话,那就是问题
    • 是的,只是playerBet。有什么问题?
    • 尝试跟随,它会起作用 Integer.parseInt(playerBet.trim());
    【解决方案3】:

    您的格式“####”只允许恰好 4 位数字。对于可变长度,您必须编写一个自定义类。 here 是一个示例类。

    我使用你的代码实现了一些东西,只有当所有 4 个数字都被填写时它才对我有用:

    import javax.swing.*;
    import javax.swing.text.*;
    import java.awt.event.*;
    import java.awt.*;
    public class tes implements ActionListener
    {
      public static JFormattedTextField playerRaiseField;
    public static void main(String[] args) throws Exception{
    JFrame j=new JFrame();
        j.setSize(400,400);
        j.setLayout(new GridLayout(2,1));
    
    MaskFormatter maskForInput;
        maskForInput=new MaskFormatter("####"); // I have tried using stars (*) too.
        maskForInput.setValidCharacters("0123456789");
    
        playerRaiseField=new javax.swing.JFormattedTextField(maskForInput);
    j.getContentPane().add(playerRaiseField);
    JButton jb=new JButton("Print out the above value");
    j.getContentPane().add(jb);
    jb.addActionListener(new tes());
    j.setVisible(true);
    }
    public void actionPerformed(ActionEvent e) throws Exception{
        System.out.println("\""+Integer.parseInt(playerRaiseField.getText())+"\"");
    }
    }
    

    【讨论】:

    • 是的,它适用于 4 个数字,但不能少,这是我的问题。
    【解决方案4】:

    java documentation

    1

    public void setMask(String mask)
                 throws ParseException
    

    2 你说你有 4 个空格。这意味着没有设置默认值,并且您没有使用无效字符。查阅以上文档。

    3 为了使其可扩展 (1-4),您必须确定输入的长度,然后通过带有 IF 的适当掩码运行它。您还可以使用默认值填充剩余的掩码,请参阅文档。

    编辑:见您在下面发布了更多代码。您不对现有字符串执行 getText 。您可以使用它从字段中获取输入。你必须以另一种方式来做。

    【讨论】:

      猜你喜欢
      • 2011-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-25
      • 2013-03-29
      • 2020-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多