将JTextField输入限制为整数

And*_*Dev 39 java swing numbers jtextfield

我知道这个问题肯定已被问过并回答了一百万次,但我找不到一个简单的解决方案.我有一个JTextField,它只接受正整数作为输入.我需要一种方法来确保没有其他任何东西在这里输入.

我已经有一个keyListener附加到此控件.删除此侦听器要处理的其他代码,我有:

       txtAnswer.addKeyListener(new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent e) {

            int key = e.getKeyCode();

            /* Restrict input to only integers */
            if (key < 96 && key > 105) e.setKeyChar('');
        };
    });
Run Code Online (Sandbox Code Playgroud)

如您所见,我正在尝试使用KeyCode来检查刚按下的键是否在整数范围内.这似乎有效.但我想要做的就是在条目超出此范围时忽略该条目.该代码e.setKeyChar('')旨在处理此问题,但它不起作用.代码将编译,但它没有明显的效果.

任何人都可以告诉我,我是否走在正确的轨道上?有什么可以替代e.setKeyChar('')它来使这项工作?还是我完全朝错误的方向走?

谢谢.

Hov*_*els 64

不要使用KeyListener,因为你会错过很多,包括粘贴文本.KeyListener也是一个非常低级的构造,因此在Swing应用程序中应该避免使用.

在SO上已经多次描述了该解决方案:使用DocumentFilter.这个网站上有几个例子,有些是我写的.

例如:using-documentfilter-filterbypass

另外,对于教程帮助,请查看:实现DocumentFilter.

编辑

例如:

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;
import javax.swing.text.PlainDocument;

public class DocFilter {
   public static void main(String[] args) {
      JTextField textField = new JTextField(10);

      JPanel panel = new JPanel();
      panel.add(textField);

      PlainDocument doc = (PlainDocument) textField.getDocument();
      doc.setDocumentFilter(new MyIntFilter());


      JOptionPane.showMessageDialog(null, panel);
   }
}

class MyIntFilter extends DocumentFilter {
   @Override
   public void insertString(FilterBypass fb, int offset, String string,
         AttributeSet attr) throws BadLocationException {

      Document doc = fb.getDocument();
      StringBuilder sb = new StringBuilder();
      sb.append(doc.getText(0, doc.getLength()));
      sb.insert(offset, string);

      if (test(sb.toString())) {
         super.insertString(fb, offset, string, attr);
      } else {
         // warn the user and don't allow the insert
      }
   }

   private boolean test(String text) {
      try {
         Integer.parseInt(text);
         return true;
      } catch (NumberFormatException e) {
         return false;
      }
   }

   @Override
   public void replace(FilterBypass fb, int offset, int length, String text,
         AttributeSet attrs) throws BadLocationException {

      Document doc = fb.getDocument();
      StringBuilder sb = new StringBuilder();
      sb.append(doc.getText(0, doc.getLength()));
      sb.replace(offset, offset + length, text);

      if (test(sb.toString())) {
         super.replace(fb, offset, length, text, attrs);
      } else {
         // warn the user and don't allow the insert
      }

   }

   @Override
   public void remove(FilterBypass fb, int offset, int length)
         throws BadLocationException {
      Document doc = fb.getDocument();
      StringBuilder sb = new StringBuilder();
      sb.append(doc.getText(0, doc.getLength()));
      sb.delete(offset, offset + length);

      if (test(sb.toString())) {
         super.remove(fb, offset, length);
      } else {
         // warn the user and don't allow the insert
      }

   }
}
Run Code Online (Sandbox Code Playgroud)

为什么这很重要?

  • 如果用户使用复制和粘贴将数据插入文本组件,该怎么办?KeyListener可以错过这个吗?
  • 您似乎希望检查数据是否可以表示int.如果他们输入的数字数据不合适怎么办?
  • 如果您想让用户以后输入双数据怎么办?用科学记数法?

  • 我遇到了无法删除最后一位的问题,如果您遇到同样的问题,则可以在remove函数中使用这段代码。`if(sb.toString()。length()== 0){super.replace(fb,offset,length,“ 0”,null); } else {if(test(sb.toString())){super.remove(fb,offset,length); } else {//警告用户,不允许插入}}`在我的示例中,我将其替换为“ 0”,但是可以将其替换为“”” (2认同)

Pet*_*eng 39

您也可以使用JFormattedTextField,这使用起来更简单.例:

public static void main(String[] args) {
    NumberFormat format = NumberFormat.getInstance();
    NumberFormatter formatter = new NumberFormatter(format);
    formatter.setValueClass(Integer.class);
    formatter.setMinimum(0);
    formatter.setMaximum(Integer.MAX_VALUE);
    formatter.setAllowsInvalid(false);
    // If you want the value to be committed on each keystroke instead of focus lost
    formatter.setCommitsOnValidEdit(true);
    JFormattedTextField field = new JFormattedTextField(formatter);

    JOptionPane.showMessageDialog(null, field);

    // getValue() always returns something valid
    System.out.println(field.getValue());
}
Run Code Online (Sandbox Code Playgroud)

  • 有了这个,用户可以在字段中插入字母. (4认同)
  • 这个方法很有效,除了一件事:一旦你输入了一个数字,第一个数字就不能用退格键删除。 (3认同)

小智 21

我无法相信我还没有在堆栈溢出的任何地方找到这个简单的解决方案,它是迄今为止最有用的.更改Document或DocumentFilter不适用于JFormattedTextField.Peter Tseng的答案非常接近.

NumberFormat longFormat = NumberFormat.getIntegerInstance();

NumberFormatter numberFormatter = new NumberFormatter(longFormat);
numberFormatter.setValueClass(Long.class); //optional, ensures you will always get a long value
numberFormatter.setAllowsInvalid(false); //this is the key!!
numberFormatter.setMinimum(0l); //Optional

JFormattedTextField field = new JFormattedTextField(numberFormatter);
Run Code Online (Sandbox Code Playgroud)

  • 在您开始在其中键入内容后,该字段也永远不会为空(即如果我输入1234并确定"实际上,我不想在此字段中输入数字",则至少会保留1个字符). (8认同)
  • @LeeCambl有可能通过使`NumberFormatter`的子类覆盖`stringToValue(String text)`来为空字符串返回`null`来解决这个问题. (2认同)

pau*_*sm4 13

这是一种使用keylistener的方法,但使用keyChar(而不是keyCode):

http://edenti.deis.unibo.it/utils/Java-tips/Validating%20numerical%20input%20in%20a%20JTextField.txt

 keyText.addKeyListener(new KeyAdapter() {
    public void keyTyped(KeyEvent e) {
      char c = e.getKeyChar();
      if (!((c >= '0') && (c <= '9') ||
         (c == KeyEvent.VK_BACK_SPACE) ||
         (c == KeyEvent.VK_DELETE))) {
        getToolkit().beep();
        e.consume();
      }
    }
  });
Run Code Online (Sandbox Code Playgroud)

另一种方法(我个人认为,与Swing的JTree模型一样过于复杂)是使用格式化文本字段:

http://docs.oracle.com/javase/tutorial/uiswing/components/formattedtextfield.html


Cha*_*han 5

我过去常常使用Key Listener,但是我没遇到过这种方法.建议的最佳方法是使用DocumentFilter.下面是我创建的用于构建仅带数字输入的文本字段的实用程序方法.请注意,它也会采取单一'.' 字符也是因为它可用于十进制输入.

public static void installNumberCharacters(AbstractDocument document) {
        document.setDocumentFilter(new DocumentFilter() {
            @Override
            public void insertString(FilterBypass fb, int offset,
                    String string, AttributeSet attr)
                    throws BadLocationException {
                try {
                    if (string.equals(".")
                            && !fb.getDocument()
                                    .getText(0, fb.getDocument().getLength())
                                    .contains(".")) {
                        super.insertString(fb, offset, string, attr);
                        return;
                    }
                    Double.parseDouble(string);
                    super.insertString(fb, offset, string, attr);
                } catch (Exception e) {
                    Toolkit.getDefaultToolkit().beep();
                }

            }

            @Override
            public void replace(FilterBypass fb, int offset, int length,
                    String text, AttributeSet attrs)
                    throws BadLocationException {
                try {
                    if (text.equals(".")
                            && !fb.getDocument()
                                    .getText(0, fb.getDocument().getLength())
                                    .contains(".")) {
                        super.insertString(fb, offset, text, attrs);
                        return;
                    }
                    Double.parseDouble(text);
                    super.replace(fb, offset, length, text, attrs);
                } catch (Exception e) {
                    Toolkit.getDefaultToolkit().beep();
                }
            }
        });
    }
Run Code Online (Sandbox Code Playgroud)