将 JTextField 输入限制为整数

2022-08-31 20:01:23

我知道这个问题一定已经被问过和回答了一百万次,但我就是找不到一个简单的解决方案。我有一个JTextField,旨在仅接受正整数作为输入。我需要一种方法来确保这里没有其他内容。

我已经有一个键列表附加到这个控件。删除此侦听器要处理的其他代码,我有这个:

       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('')

谢谢。


答案 1

不要为此使用KeyListener,因为您将错过很多内容,包括粘贴文本。此外,KeyListener 是一种非常低级的构造,因此,在 Swing 应用程序中应避免使用。

该解决方案已在 SO: Use a 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
      }

   }
}

为什么这很重要?

  • 如果用户使用复制和粘贴将数据插入到文本组件中,该怎么办?密钥列表可能会错过这个吗?
  • 您似乎希望检查数据是否可以表示整数。如果他们输入的数字数据不合适,该怎么办?
  • 如果要允许用户稍后输入双重数据,该怎么办?用科学记数法?

答案 2

您也可以使用 ,这使用起来要简单得多。例: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());
}