Java 带有maskFormatter的JFormattedTextField抛出NumberFormatException

Java 带有maskFormatter的JFormattedTextField抛出NumberFormatException,java,swing,parsing,input,integer,Java,Swing,Parsing,Input,Integer,我有一个使用以下掩码格式化程序的JFormattedTextField: private MaskFormatter maskForInput; maskForInput=new MaskFormatter("####"); // I have tried using stars (*) too. maskForInput.setValidCharacters("0123456789"); javax.swing.JFormattedTextField play

我有一个使用以下掩码格式化程序的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())
从该字段返回的
字符串时,我总是会得到
NumberFormatException
,这可能是由于用户输入时留下的空格。 要澄清这一点:

例如,如果用户输入
560
,则留下一个尾随空格,因此我正在读取的字符串是
560()
,当试图将该
字符串
解析为
int
时,会引发此异常。有解决办法吗?如何修改掩码格式化程序以接受1到4位数字,而不是始终固定4位数字


注意:奇怪的是,在返回的
字符串上使用
trim()
仍然没有删除多余的空白字符…

因为我不确定您是如何使用trim的,我建议您尝试以下代码行来删除空格: 如前所述,以下代码应起作用:

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

Integer.parseInt(playerBetWithoutSpaces);
一,


你说你有4个空格。这意味着没有设置默认值,也没有使用invalidcharacters。查阅上述文档

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

编辑:请参阅下面发布的更多代码。不能对现有字符串执行getText。您可以使用它从字段中获取输入。您必须以另一种方式执行此操作。

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

我使用您的代码实现了一些东西,只有在填写了所有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())+"\"");
}
}

你的期望有很多地方不对劲

首先,您似乎认为格式化字段可以有任意数量的字符。事实并非如此(虽然您可以获取文本,但字段仍处于它认为无效的状态)。格式化字段要求必须填充掩码的所有位置

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

第三,返回的文本用掩码的占位符字符(
MaskFormatter#getPlaceholder
)填充,该字符可能是空格,也可能不是空格,因此
String#trim
可能没有帮助

如果您希望用户只能输入一个数字值,该值可以由0—N个字符组成,那么您就应该考虑使用<代码>文档过滤器> /代码>应用于正常<代码> jTrutfield

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

如果你打印出引号之间的字符串,你得到了什么?@Jake223我得到了4个空格。现在这很奇怪…请参阅文档。特别是占位符字符。事实并非如此,我首先将
getText()
返回的值存储到字符串中,然后在此
字符串上使用
.trim()
。这可能不会有任何更改,但感谢您的帮助。
String playerBet=playerRaiseField.getText()然后
playerBet.trim()然后将什么传递给Integer.parseInt??只需播放设置,如果是,那么这就是问题。是的,只需
playerBet
。问题是什么?请尝试以下操作,它将工作于Integer.parseInt(playerBet.trim());是的,它适用于4个数字,但不能少于4个,这是我的问题。
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());
                }
            });
        }
    }
}