防止 Java Swing JTextField 中输入字符

3
我正在使用Java Swing,并尝试只允许在JTextField中输入数字。当输入字符时,我希望显示一个无效消息,并防止将该字符输入到JTextField中。
        idText.addKeyListener(new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent e) {
            try
            {
                int i = Integer.parseInt(idText.getText()+e.getKeyChar());
                validText.setText("");
            }
            catch(NumberFormatException e1) {
                e.consume();
                validText.setText("Numbers Only!");
            }
        }
    });

由于某些原因,e.consume()的效果与我预期的不同,我无法输入字符。


keyTyped方法替换keyPressed方法可以吗? - undefined
2个回答

6
一般情况下,不建议在JTextField中添加自定义KeyListener以防止字符输入。对于只接受数字输入的组件,最好使用已经创建好的组件,这样更容易让用户使用和程序员编写。
以下是其中两个组件:
  1. JSpinner
  2. JFormattedTextField
如果您坚持要自行完成,最好使用DocumentFilter而不是KeyListener进行限制。另外,此处提供了另一个例子。
除了上述示例,这里也提供我的解决方案:
public class DocumentFilterExample extends JFrame {
    public DocumentFilterExample() {
        super("example");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new FlowLayout());

        JTextField field = new JTextField(15);
        AbstractDocument document = (AbstractDocument) field.getDocument();
        document.setDocumentFilter(new OnlyDigitsDocumentFilter());
        add(field);

        setLocationByPlatform(true);
        pack();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new DocumentFilterExample().setVisible(true));
    }

    private static class OnlyDigitsDocumentFilter extends DocumentFilter {
        @Override
        public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
            text = keepOnlyDigits(text);
            super.replace(fb, offset, length, text, attrs);
        }

        @Override
        public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
            string = keepOnlyDigits(string);
            super.insertString(fb, offset, string, attr);
        }

        private String keepOnlyDigits(String text) {
            StringBuilder sb = new StringBuilder();
            text.chars().filter(Character::isDigit).forEach(sb::append);
            return sb.toString();
        }
    }
}

2
推荐不要使用KeyListener,获得1000个赞同。 - undefined
我使用了你的答案,但是我不得不在keepOnlyDigits方法的流式代码中添加以下代码.mapToObj(Character::toChars)。我提供了一个更详细的答案。 - undefined

0
我推荐使用已经存在的DocumentFilterExample答案,但是我要提交一个“答案”来添加一些额外的代码,这些代码是我必须使用的,以使其正常工作。
我不得不修改keepOnlyDigits方法,将int字符值映射到char字符值。
        private String keepOnlyDigits(String text) {
            StringBuilder sb = new StringBuilder();
            text.chars().filter(Character::isDigit)
                    .peek(charInt -> System.out.println("before: " + charInt))
                    .mapToObj(Character::toChars) // Added this line
                    .peek(toChar -> System.out.println("after: " + toChar[0]))
                    .forEach(sb::append);
            return sb.toString();
        }

这是带有该更改的输出,运行DocumentFilterExamplemain方法: {{link1:enter image description here}}
我添加了peek来显示在我的更改之前和之后打印出的值。
我的更改是将.mapToObj(Character::toChars)添加到Stream代码中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接