Restriction de L'entrée JTextField aux entiers [dupliquer]

cette question a déjà une réponse ici:

  • est-il possible d'accepter uniquement des valeurs numériques dans un champ Jtext? 19 réponses

je sais que cette question a dû être posée et répondue un million de fois, mais je ne peux pas trouver une solution facile. J'ai un component swing jtextfield que est destiné à accepter uniquement des entiers positifs comme entrée. J'ai besoin d'un moyen pour s'assurer que rien d'autre n'obtient d'entrée ici.

j'ai déjà un keyListener attaché à ce contrôle. En enlevant l'autre code que cet auditeur est là pour gérer, j'ai ceci:

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

comme vous pouvez le voir, j'essaie d'utiliser le code de la touche pour vérifier si la touche juste pressée tombe dans la gamme des entiers. Cela semble fonctionner. Mais ce que je veux faire est de simplement le mépris de l'entrée si elle tombe en dehors de cette plage. Le code e.setKeyChar('') était destiné à gérer cela, mais il ne fonctionne pas. Le code compilera, mais il n'a aucun effet visible.

quelqu'un Peut-il me dire si je suis sur la bonne voie? Avec quoi puis-je remplacer e.setKeyChar('') pour que cela fonctionne? Ou suis-je totalement dans la mauvaise direction?

Merci.

34
demandé sur JimmyPena 2012-06-19 05:41:44

6 réponses

N'utilisez pas de KeyListener pour cela car vous manquerez beaucoup y compris le collage de texte. De plus, un KeyListener est une construction de très bas niveau et en tant que tel, doit être évité dans les applications Swing.

la solution a été décrite plusieurs fois sur SO: utilisez un DocumentFilter . Il y a plusieurs exemples de cela sur ce site, certains écrits par moi.

par exemple: utilisant-documentfilter-filterbypass

également pour l'aide de tutoriel, s'il vous plaît regarder: mise en œuvre D'un DocumentFilter .

Modifier

par exemple:

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
      }

   }
}

Pourquoi est-ce important?

  • Que si l'utilisateur utilise le copier-coller pour insérer des données dans le composant de texte? Un KeyListener peut rater ça?
  • vous semblez désirer vérifiez que les données peuvent représenter un int. Et s'ils entrent des données numériques qui ne correspondent pas?
  • Que faire si vous voulez permettre à l'utilisateur d'entrer plus tard des données doubles? En notation scientifique?
56
répondu Hovercraft Full Of Eels 2017-05-23 12:10:43

Vous pouvez également utiliser JFormattedTextField , qui est beaucoup plus simple à utiliser. Exemple:

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());
}
36
répondu Peter Tseng 2016-06-09 01:12:41

Je ne peux pas croire que je n'ai pas trouvé cette solution simple n'importe où sur le débordement de pile encore, il est de loin le plus utile. Changer le document ou DocumentFilter ne fonctionne pas pour JFormattedTextField. La réponse de Peter Tseng est très proche.

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);
17
répondu Umi 2013-06-18 06:24:28

Voici une approche qui utilise un keylistener, mais utilise le keyChar (au lieu du 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();
      }
    }
  });

une autre approche (que personnellement je trouve presque aussi compliquée que le modèle JTree de Swing) est d'utiliser des Champs de texte formatés:

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

11
répondu paulsm4 2012-06-19 01:49:19

j'avais l'habitude d'utiliser L'auditeur clé pour cela, mais j'ai échoué grand temps avec cette approche. Comme recommandé déjà, la meilleure approche est d'utiliser un Filteurdocument. Ci-dessous est une méthode utilitaire que j'ai créé pour construire des textfields avec seulement l'entrée de nombre. Il suffit de se méfier que cela prendra aussi simple'."ainsi car il est utilisable pour les décimales d'entrée.

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();
                }
            }
        });
    }
5
répondu Chan 2012-06-19 02:14:44

lorsque vous tapez des nombres entiers à JtextField1 après la sortie de la clé , il ira à inside try, pour tout autre caractère, il lancera NumberFormatException. Si vous mettez la chaîne vide à jTextField1 à l'intérieur de la capture de sorte que l'utilisateur ne peut pas taper d'autres clés sauf des nombres positifs parce que JTextField1 sera blanchi pour chaque mauvaise tentative.

 //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("");
    }
}   
3
répondu user3498019 2015-10-05 17:52:51