web-dev-qa-db-fra.com

Accepter uniquement les nombres et un point dans Java TextField

J'ai un champ textField dans lequel je n'accepte que les chiffres du clavier, mais je dois maintenant le modifier car il s'agit d'un "champ textField" et j'aurais également besoin d'un point "" pour tout type de prix.

Comment puis-je changer cela afin d'obtenir ce dont j'ai besoin?

ptoMinimoField = new JTextField();
        ptoMinimoField.setBounds(348, 177, 167, 20);
        contentPanel.add(ptoMinimoField);
        ptoMinimoField.setColumns(10);
        ptoMinimoField.addKeyListener(new KeyAdapter() {
            public void keyTyped(KeyEvent e) {
                char caracter = e.getKeyChar();
                if (((caracter < '0') || (caracter > '9'))
                        && (caracter != '\b')) {
                    e.consume();
                }
            }
        });
8
Agustín

Comme suggéré par Oracle, Utiliser les champs de texte mis en forme

Les champs de texte formatés permettent aux développeurs de spécifier le jeu de caractères valide pouvant être saisi dans un champ de texte. 

amountFormat = NumberFormat.getNumberInstance();
...
amountField = new JFormattedTextField(amountFormat);
amountField.setValue(new Double(amount));
amountField.setColumns(10);
amountField.addPropertyChangeListener("value", this);
11
Suresh Atta

JTextField txField = new DoubleJTextField ();

Créez un fichier DoubleJTextField.Java et soyez heureux

public class DoubleJTextField extends JTextField {
    public DoubleJTextField(){
        addKeyListener(new KeyAdapter() {
            public void keyTyped(KeyEvent e) {
                char ch = e.getKeyChar();

                if (!isNumber(ch) && !isValidSignal(ch) && !validatePoint(ch)  && ch != '\b') {
                    e.consume();
                }
            }
        });

    }

    private boolean isNumber(char ch){
        return ch >= '0' && ch <= '9';
    }

    private boolean isValidSignal(char ch){
        if( (getText() == null || "".equals(getText().trim()) ) && ch == '-'){
            return true;
        }

        return false;
    }

    private boolean validatePoint(char ch){
        if(ch != '.'){
            return false;
        }

        if(getText() == null || "".equals(getText().trim())){
            setText("0.");
            return false;
        }else if("-".equals(getText())){
            setText("-0.");
        }

        return true;
    }
}
6
Wender

Je viens d'utiliser un bloc try-catch

try {// if is number
    Integer.parseInt(String);
} catch (NumberFormatException e) {
    // else then do blah
}
5
Brayan Byrdsong

Ne jamais utiliser un KeyListener pour cela. Votre code ci-dessus a deux bogues graves, tous deux causés par l'utilisation d'un KeyListener. Tout d'abord, il manquera tout texte collé. Chaque fois que je trouve un champ qui filtre les non-chiffres, j'essaie toujours de coller du texte, juste pour le plaisir. Neuf fois sur dix, le texte est accepté, car ils ont utilisé un auditeur principal. 

Deuxièmement, vous n'avez pas filtré les modificateurs. Si l'utilisateur essaie de sauvegarder son travail en tapant control-s alors qu'il se trouve dans ce champ, votre écouteur de clé utilisera l'événement. Et si votre application attribue, par exemple, un raccourci clavier control-5 ou alt-5 à une action, ce KeyListener ajoutera un 5 au champ lorsqu’il le saisira, même si l’utilisateur n’a pas tenté de saisir un caractère. Vous vous êtes rendu compte que vous deviez passer la touche de retour arrière, mais ce n'est pas tout ce que vous avez besoin de passer. Vos touches de direction ne fonctionneront pas. Ni vos touches de fonction. Vous pouvez résoudre tous ces problèmes, mais cela commence à faire beaucoup de travail.

Il existe un troisième inconvénient, mais il n’apparaît que si vous adaptez votre application à un alphabet étranger, en particulier un alphabet qui nécessite plusieurs frappes au clavier pour générer un seul caractère, tel que le chinois. Ces alphabets rendent KeyListeners inutiles.

Le problème est la suivante. Vous devez filtrer les caractères, mais les KeyListeners ne traitent pas de caractères, mais de touches, qui ne sont pas identiques: toutes les frappes ne génèrent pas de caractères et tous les caractères ne sont pas générés par des frappes. Vous avez besoin d'une approche qui examine les caractères une fois qu'ils ont été générés et après que les frappes modifiées ont déjà été filtrées.

L’approche la plus simple consiste à utiliser un JFormattedTextField, mais je n’ai jamais aimé cette approche, car elle ne formate ni ne filtre pas au fur et à mesure de la frappe. Donc, au lieu de cela, je vais utiliser un DocumentFilter. Les filtres DocumentFilters ne fonctionnent pas sur les touches, ils agissent sur les chaînes de texte lorsqu'elles sont insérées dans le modèle de données de votre JTextField. Par conséquent, toutes les touches de contrôle, les touches de direction et les touches de fonction et autres ne parviennent même pas au DocumentFilter. Tout le texte collé passe également par DocumentFilter. De plus, pour les langues nécessitant trois touches pour générer un seul caractère, DocumentFilter n'est pas appelé jusqu'à ce que le caractère soit généré. Voici à quoi ça ressemble:

    ptoMinimoField = new JTextField();
    ptoMinimoField.setBounds(348, 177, 167, 20); // Don't do this! See below.
    contentPanel.add(ptoMinimoField);
    ptoMinimoField.setColumns(10);

    PlainDocument document = (PlainDocument) ptoMinimoField.getDocument();
    document.setDocumentFilter(new DigitFilter());
}

La classe DigitFilter ressemble à ceci:

public class DigitFilter extends DocumentFilter {
    @Override
    public void insertString(FilterBypass fb, int offset, String text, 
            AttributeSet attr) throws BadLocationException {
        super.insertString(fb, offset, revise(text), attr);
    }

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

    private String revise(String text) {
        StringBuilder builder = new StringBuilder(text);
        int index = 0;
        while (index < builder.length()) {
            if (accept(builder.charAt(index))) {
                index++;
            } else {
                // Don't increment index here, or you'll skip the next character!
                builder.deleteCharAt(index);
            }
        }
        return builder.toString();
    }

    /**
     * Determine if the character should remain in the String. You may
     * override this to get any matching criteria you want. 
     * @param c The character in question
     * @return true if it's valid, false if it should be removed.
     */
    public boolean accept(final char c) {
        return Character.isDigit(c) || c == '.';
    }
}

Vous pourriez écrire ceci en tant que classe interne, mais j'ai créé une classe séparée afin de pouvoir remplacer la méthode accept () afin d'utiliser les critères de votre choix. Vous remarquerez peut-être aussi que je ne teste pas les chiffres en écrivant ceci:

(c < '0') || (c > '9')

Au lieu de cela, je fais ceci:

Character.isDigit()

Ceci est plus rapide, plus propre et fonctionne avec des systèmes de numérotation étrangers. Je n'ai pas non plus besoin de votre test pour le caractère de retour arrière, '\ b'. Je suppose que votre premier KeyListener était en train de filtrer la clé de retour arrière, ce qui était votre premier indice que c'était la mauvaise approche.

Et sur une note indépendante, ne codez pas en dur vos positions de composant. Apprenez à utiliser les LayoutManagers. Ils sont faciles à utiliser et rendront votre code beaucoup plus facile à gérer.

3
MiguelMunoz

Avez-vous examiné un JFormattedTextField? Il semblerait que cela fasse ce que vous voulez.

2
arcy

Entrez le nombre double de JTextField en Java

private boolean dot = false;
private void txtMarkKeyTyped(Java.awt.event.KeyEvent evt) {                                 
    char vChar = evt.getKeyChar();
    if (txtMark.getText().equals(""))
        dot = false;
    if (dot == false){
        if (vChar == '.') dot = true;
        else if (!(Character.isDigit(vChar)
                || (vChar == KeyEvent.VK_BACK_SPACE)
                || (vChar == KeyEvent.VK_DELETE))) {
                evt.consume();
        }
    } else {
        if (!(Character.isDigit(vChar)
                || (vChar == KeyEvent.VK_BACK_SPACE)
                || (vChar == KeyEvent.VK_DELETE))) {
                evt.consume();
        }
    }
}
1
Vũ Trung Sơn

Ce morceau de code;

if (((caracter < '0') || (caracter > '9'))
                    && (caracter != '\b')) {

décide si l'événement clé doit être consommé. Vous devez mettre à jour la condition afin qu'elle ne consomme pas le caractère de point.

1
Qwerky
JTextField txtMyTextField = new JTextField();

numOnly(txtMyTextField);

public void numOnly(Object objSource){
    ((Component) objSource).addKeyListener(new KeyListener() {

        @Override
        public void keyTyped(KeyEvent e) {
            String filterStr = "0123456789.";
            char c = (char)e.getKeyChar();
            if(filterStr.indexOf(c)<0){
                e.consume();
            }
        }
        @Override
        public void keyReleased(KeyEvent e) {}

        @Override
        public void keyPressed(KeyEvent e) {}
    });
}

AVERTISSEMENT: cette fonction ne suit pas la documentation Java appropriée guider.

1
kulakesh

J'utilise cette solution, c'est simple et efficace:

                jtextfield.addKeyListener(new KeyAdapter() {
                public void keyTyped(KeyEvent e) {
                    char vChar = e.getKeyChar();
                    if (!(Character.isDigit(vChar)
                            || (vChar == KeyEvent.VK_BACK_SPACE)
                            || (vChar == KeyEvent.VK_DELETE))) {
                        e.consume();
                    }
                }
            });
0
Abdellah Benhammou
JTextField textField = new JTextField();
textField.setColumns(10);

textField.addKeyListener(new KeyAdapter() {
    @Override
    public void KeyTyped(KeyEvent e) {
        if (!(e.getKeyChar() >= '0' && e.getKeyChar() <= '9')) {
            e.consume();
        }
    }
})

c'est la méthode la plus simple que j'ai trouvée jusqu'à présent, et cela fonctionne sans erreur

0
Kickass Kicchu

/////////////

    JTextField ptoMinimoField = new JTextField();
    ptoMinimoField.addKeyListener(new KeyAdapter() {
        public void keyTyped(KeyEvent e) {
             boolean ret = true;
                try {

                    Double.parseDouble(ptoMinimoField.getText()+e.getKeyChar());
                }catch (NumberFormatException ee) {
                    ret = false;
                }


            if (!ret) {
                e.consume();
            }
        }
    });
0
Alireza Ravandi
private boolean point = false;
private void txtProductCostPriceAddKeyTyped(Java.awt.event.KeyEvent evt)   
{
    char Char = evt.getKeyChar();
    if (txtProductCostPriceAdd.getText().equals(""))
        point = false;
    if (point == false){
        if (Char == '.') point = true;
        else if (!(Character.isDigit(Char) || (Char == KeyEvent.VK_BACK_SPACE) || (Char == KeyEvent.VK_DELETE))) {
                evt.consume();
        }
    } else {
        if (!(Character.isDigit(Char) || (Char == KeyEvent.VK_BACK_SPACE) || (Char == KeyEvent.VK_DELETE))) {
                evt.consume();
        }
    }
}
0
Noiwong Suwijak

peut peut-être vous aider à filtrer les clés tapées seulement le nombre et le point

public void filterHanyaAngkaDot(Java.awt.event.KeyEvent evt){
      char c = evt.getKeyChar();
      if (! ((Character.isDigit(c) ||
              (c == KeyEvent.VK_BACK_SPACE) ||
              (c == KeyEvent.VK_DELETE))
              )&& c==KeyEvent.VK_COMMA
              )
      {
          evt.consume();
      }
 }
0
irbef