Ограничение ввода JTextField для целых чисел

Я знаю, что этот вопрос, должно быть, спросил и ответил миллион раз, но я просто не могу найти легкое решение. У меня есть JTextField, который должен принимать только положительные целые числа в качестве входных данных. Мне нужен способ убедиться, что здесь ничего не вводит.

У меня уже есть keyListener, прикрепленный к этому элементу управления. Удалив другой код, который должен обработать этот слушатель, у меня есть следующее:

txtAnswer.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); /* Restrict input to only integers */ if (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()); } 

Не могу поверить, что я еще не нашел это простое решение в любом месте при переполнении стека, это, безусловно, самое полезное. Изменение документа или DocumentFilter не работает для JFormattedTextField. Ответ Петра Цзэна очень близок.

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

Другой подход (который лично я считаю почти сложным, как модель JTree от Swing) заключается в использовании форматированных текстовых полей:

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. Если вы установите пустую строку в jTextField1 внутри catch, чтобы пользователь не мог вводить другие ключи, кроме положительных чисел, потому что 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(""); } } 
  • java swingworker thread для обновления основного Gui
  • Сохранение правильного стиля при поиске текста
  • Cytoscape как инструменты в java для построения графика
  • JTable, как работаетEditor
  • SwingUtilities.invokeLater
  • Как правильно использовать собственные средства визуализации для рисования конкретных ячеек в JTable?
  • разрешение отклонено при чтении / записи файла с помощью приложения (.jar) в mac
  • Обновление JLabel каждые X секунд из ArrayList - Java
  • Широкоэкранный набор приложений - Java Swing
  • Измените размер изображения в соответствии с JLabel
  • Java KeyListener не регистрирует клавиши со стрелками
  • Давайте будем гением компьютера.