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

正如你所看到的,我试图使用KeyCode来检查刚刚按下的键是否在整数范围内。 这似乎工作。 但是我想要做的就是只要不在这个范围之内就忽视这个条目。 代码e.setKeyChar('')是为了处理这个问题,但它不起作用。 代码将被编译,但是没有可见的效果。

有人可以告诉我,如果我在正确的轨道上? 我可以用e.setKeyChar('')替换这个工作吗? 还是我完全走错了方向?

谢谢。

不要使用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 } } } 

为什么这很重要?

  • 如果用户使用复制和粘贴将数据插入文本组件,该怎么办? KeyListener可能会错过这个?
  • 你似乎希望检查数据可以代表一个int。 如果他们输入不合适的数字数据呢?
  • 如果你想让用户以后输入双重数据呢? 在科学记数法?

您也可以使用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()); } 

我不敢相信我在堆栈溢出的任何地方都没有找到这个简单的解决方案,但它是迄今为止最有用的。 更改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); 

下面是一个使用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(); } } }); 

另一种方法(我个人觉得它几乎和Swing的JTree模型一样复杂)是使用格式化文本字段:

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

我曾经为此使用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(); } } }); } 

当你在键释放后向JtextField1键入整数时,它将进入try内部,对于任何其他字符,它将抛出NumberFormatException。 如果在catch中设置了空字符串jTextField1,那么用户不能输入除正数以外的任何其他键,因为每次错误尝试都会清除JTextField1。

  //Fields int x; JTextField jTextField1; //Gui Code Here private void jTextField1KeyReleased(java.awt.event.KeyEvent evt) { try { x = Integer.parseInt(jTextField1.getText()); } catch (NumberFormatException nfe) { jTextField1.setText(""); } }