Quelle est la méthode recommandée pour créer un TextField numérique dans JavaFX?


85

J'ai besoin de restreindre l'entrée dans un TextField aux entiers. Aucun conseil?


3
Remarque: écouter le textProperty est faux ! C'était le mieux que l'on puisse faire avant d'avoir un TextFormatter (depuis fx8u40 ou plus). Depuis lors, la règle de base s'applique: en général, il est considéré comme une mauvaise pratique de modifier la valeur observée dans cette méthode et l'utilisation d'un TextFormatter est la seule solution acceptable.
kleopatra

Réponses:


118

Fil très ancien, mais cela semble plus net et supprime les caractères non numériques s'il est collé.

// force the field to be numeric only
textField.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue, 
        String newValue) {
        if (!newValue.matches("\\d*")) {
            textField.setText(newValue.replaceAll("[^\\d]", ""));
        }
    }
});

3
Fonctionne à merveille. Notez que vous pouvez également utiliser \\D+(ou simplement \\D) à la place de [^\\d], si vous souhaitez enregistrer quelques caractères.
ricky3350

5
Encore plus simple est de redéfinir le texte sur oldValue. De cette façon, vous n'avez pas à vous soucier des remplacements de regex (ce qui n'a malheureusement pas fonctionné pour moi).
geisterfurz007

@ geisterfurz007 Cela donne la possibilité de supprimer les éléments non numériques du texte collé.
Evan Knowles le

10
Obsolète, voir la réponse TextFormatter ci-dessous.
gerardw

3
Pourrait également utiliser Integer.parseInt(newValue)et utiliser tryet catchdétecter une erreur surNumberFormatException
Pixel

43

Mise à jour avril 2016

Cette réponse a été créée il y a quelques années et la réponse originale est aujourd'hui largement obsolète.

Depuis Java 8u40, Java a un TextFormatter qui est généralement le meilleur pour appliquer la saisie de formats spécifiques tels que les nombres sur JavaFX TextFields:

Voir également d'autres réponses à cette question qui mentionnent spécifiquement TextFormatter.


Réponse originale

Il y a quelques exemples de cela dans cet essentiel , j'ai dupliqué l'un des exemples ci-dessous:

// helper text field subclass which restricts text input to a given range of natural int numbers
// and exposes the current numeric int value of the edit box as a value property.
class IntField extends TextField {
  final private IntegerProperty value;
  final private int minValue;
  final private int maxValue;

  // expose an integer value property for the text field.
  public int  getValue()                 { return value.getValue(); }
  public void setValue(int newValue)     { value.setValue(newValue); }
  public IntegerProperty valueProperty() { return value; }

  IntField(int minValue, int maxValue, int initialValue) {
    if (minValue > maxValue) 
      throw new IllegalArgumentException(
        "IntField min value " + minValue + " greater than max value " + maxValue
      );
    if (maxValue < minValue) 
      throw new IllegalArgumentException(
        "IntField max value " + minValue + " less than min value " + maxValue
      );
    if (!((minValue <= initialValue) && (initialValue <= maxValue))) 
      throw new IllegalArgumentException(
        "IntField initialValue " + initialValue + " not between " + minValue + " and " + maxValue
      );

    // initialize the field values.
    this.minValue = minValue;
    this.maxValue = maxValue;
    value = new SimpleIntegerProperty(initialValue);
    setText(initialValue + "");

    final IntField intField = this;

    // make sure the value property is clamped to the required range
    // and update the field's text to be in sync with the value.
    value.addListener(new ChangeListener<Number>() {
      @Override public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, Number newValue) {
        if (newValue == null) {
          intField.setText("");
        } else {
          if (newValue.intValue() < intField.minValue) {
            value.setValue(intField.minValue);
            return;
          }

          if (newValue.intValue() > intField.maxValue) {
            value.setValue(intField.maxValue);
            return;
          }

          if (newValue.intValue() == 0 && (textProperty().get() == null || "".equals(textProperty().get()))) {
            // no action required, text property is already blank, we don't need to set it to 0.
          } else {
            intField.setText(newValue.toString());
          }
        }
      }
    });

    // restrict key input to numerals.
    this.addEventFilter(KeyEvent.KEY_TYPED, new EventHandler<KeyEvent>() {
      @Override public void handle(KeyEvent keyEvent) {
        if(intField.minValue<0) {
                if (!"-0123456789".contains(keyEvent.getCharacter())) {
                    keyEvent.consume();
                }
            }
            else {
                if (!"0123456789".contains(keyEvent.getCharacter())) {
                    keyEvent.consume();
                }
            }
      }
    });

    // ensure any entered values lie inside the required range.
    this.textProperty().addListener(new ChangeListener<String>() {
      @Override public void changed(ObservableValue<? extends String> observableValue, String oldValue, String newValue) {
        if (newValue == null || "".equals(newValue) || (intField.minValue<0 && "-".equals(newValue))) {
          value.setValue(0);
          return;
        }

        final int intValue = Integer.parseInt(newValue);

        if (intField.minValue > intValue || intValue > intField.maxValue) {
          textProperty().setValue(oldValue);
        }

        value.set(Integer.parseInt(textProperty().get()));
      }
    });
  }
}

41

Je sais que c'est un fil assez ancien, mais pour les futurs lecteurs, voici une autre solution que j'ai trouvée assez intuitive:

public class NumberTextField extends TextField
{

    @Override
    public void replaceText(int start, int end, String text)
    {
        if (validate(text))
        {
            super.replaceText(start, end, text);
        }
    }

    @Override
    public void replaceSelection(String text)
    {
        if (validate(text))
        {
            super.replaceSelection(text);
        }
    }

    private boolean validate(String text)
    {
        return text.matches("[0-9]*");
    }
}

Edit: Merci none_ et SCBoy pour vos suggestions d'améliorations.


1
Quelqu'un sait-il quelle expression régulière utiliser pour les nombres décimaux (par exemple 123,456)? La valeur du paramètre de fonction de validation (texte) "texte" est le dernier caractère édité par l'utilisateur, et non la chaîne entière dans le champ de texte, par conséquent l'expression régulière peut ne pas correspondre correctement. Par exemple, j'utilise cette commande comme ceci: text.matches("\\d+"); et je ne peux supprimer aucun caractère dans le champ de texte
mils

1
@mils Regardez ici et ici .
vellotis le

1
Je pense que c'est une bonne solution, mais je changerais une chose. Au lieu d'écrire text.matches ("[0-9] *"), je créerais une variable pour le motif et la compilerais. Dans votre code, le modèle est compilé à chaque fois que quelqu'un écrit un caractère dans un champ, ce qui est coûteux pour le processeur et la mémoire. J'ajouterais donc la variable: Private static Pattern integerPattern = Pattern.compile ("[0-9] *"); Et remplacez le corps de validation par: integerPattern.matcher (text) .matches ();
P. Jowko

38

À partir de JavaFX 8u40, vous pouvez définir un objet TextFormatter sur un champ de texte:

UnaryOperator<Change> filter = change -> {
    String text = change.getText();

    if (text.matches("[0-9]*")) {
        return change;
    }

    return null;
};
TextFormatter<String> textFormatter = new TextFormatter<>(filter);
fieldNport = new TextField();
fieldNport.setTextFormatter(textFormatter);

Cela évite à la fois de sous-classer et de dupliquer les événements de modification que vous obtiendrez lorsque vous ajoutez un écouteur de changement à la propriété text et modifiez le texte dans cet écouteur.


30

Le TextInputa unTextFormatter qui peut être utilisé pour formater, convertir et limiter les types de texte qui peuvent être saisis.

le TextFormatter a un filtre qui peut être utilisé pour rejeter l'entrée. Nous devons définir ceci pour rejeter tout ce qui n'est pas un entier valide. Il a également un convertisseur que nous devons définir pour convertir la valeur de la chaîne en une valeur entière que nous pouvons lier plus tard.

Permet de créer un filtre réutilisable:

public class IntegerFilter implements UnaryOperator<TextFormatter.Change> {
    private final static Pattern DIGIT_PATTERN = Pattern.compile("\\d*");

    @Override
    public Change apply(TextFormatter.Change aT) {
        return DIGIT_PATTERN.matcher(aT.getText()).matches() ? aT : null;
    }
}

Le filtre peut faire l'une des trois choses suivantes, il peut renvoyer le changement non modifié pour l'accepter tel quel, il peut modifier le changement d'une manière qu'il juge appropriée ou il peut revenir null pour rejeter le changement dans son ensemble.

Nous utiliserons la norme IntegerStringConverter comme convertisseur.

En mettant tout cela ensemble, nous avons:

TextField textField = ...;

TextFormatter<Integer> formatter = new TextFormatter<>(
    new IntegerStringConverter(), // Standard converter form JavaFX
    defaultValue, 
    new IntegerFilter());
formatter.valueProperty().bindBidirectional(myIntegerProperty);

textField.setTextFormatter(formatter);

Si vous ne voulez pas avoir besoin d'un filtre réutilisable, vous pouvez faire cette fantaisie à une seule ligne à la place:

TextFormatter<Integer> formatter = new TextFormatter<>(
    new IntegerStringConverter(), 
    defaultValue,  
    c -> Pattern.matches("\\d*", c.getText()) ? c : null );

21

Je n'aime pas les exceptions donc j'ai utilisé la matchesfonction de String-Class

text.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue, 
        String newValue) {
        if (newValue.matches("\\d*")) {
            int value = Integer.parseInt(newValue);
        } else {
            text.setText(oldValue);
        }
    }
});

1
parfois vous avez une exception, car le nuber peut être trop grand.
schlagi123

1
Astuce: remplacez l'expression régulière "\\ d +" par "\\ d *". Cela vous permettra de supprimer tous les caractères du champ de saisie de texte (utilisez retour arrière / suppression pour effacer le champ).
Guus

1
N'oubliez pas de régler la position du curseur après l'avoir remise à l'ancienne valeur:textField.positionCaret(textField.getLength());
hsson

Remplacez la première condition if par: if (newValue.matches("\\d*") && newValue.getText().length < 5) si vous souhaitez limiter l'entrée à 4 chiffres dans ce cas.
Cappuccino90

@ Cappuccino90 Vous devriez changer les instructions car la vérification de la longueur est beaucoup moins chère à chaque hit que l'analyse d'une regex
thatsIch

9

A partir de Java SE 8u40 , pour un tel besoin vous pouvez utiliser un " entier " Spinnerpermettant de sélectionner en toute sécurité un entier valide en utilisant les touches fléchées haut / bas du clavier ou les boutons fléchés haut / bas fournis.

Vous pouvez également définir un min , un max et une valeur initiale pour limiter les valeurs autorisées et un montant à incrémenter ou décrémenter de, par étape.

Par exemple

// Creates an integer spinner with 1 as min, 10 as max and 2 as initial value
Spinner<Integer> spinner1 = new Spinner<>(1, 10, 2);
// Creates an integer spinner with 0 as min, 100 as max and 10 as initial 
// value and 10 as amount to increment or decrement by, per step
Spinner<Integer> spinner2 = new Spinner<>(0, 100, 10, 10);

Exemple de résultat avec un spinner " entier " et un spinner " double "

entrez la description de l'image ici

Une double flèche est un contrôle de champ de texte sur une seule ligne qui permet à l'utilisateur de sélectionner un nombre ou une valeur d'objet dans une séquence ordonnée de ces valeurs. Les spinners fournissent généralement une paire de minuscules boutons fléchés pour parcourir les éléments de la séquence. Les touches fléchées haut / bas du clavier font également défiler les éléments. L'utilisateur peut également être autorisé à saisir une valeur (légale) directement dans le spinner. Bien que les listes déroulantes fournissent des fonctionnalités similaires, les filateurs sont parfois préférés car ils ne nécessitent pas de liste déroulante qui peut masquer des données importantes, et aussi parce qu'ils permettent des fonctionnalités telles que le retour de la valeur maximale à la valeur minimale (par exemple, du plus grand entier positif à 0).

Plus de détails sur le contrôle Spinner


Les gens ne devraient pas que le spinner ne valide pas la saisie de texte ou la mise au point perdue
geometrikal

7

La réponse préférée peut être encore plus petite si vous utilisez Java 1.8 Lambdas

textfield.textProperty().addListener((observable, oldValue, newValue) -> {
    if (newValue.matches("\\d*")) return;
    textfield.setText(newValue.replaceAll("[^\\d]", ""));
});

6
TextField text = new TextField();

text.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable,
            String oldValue, String newValue) {
        try {
            Integer.parseInt(newValue);
            if (newValue.endsWith("f") || newValue.endsWith("d")) {
                manualPriceInput.setText(newValue.substring(0, newValue.length()-1));
            }
        } catch (ParseException e) {
            text.setText(oldValue);
        }
    }
});

La ifclause est importante pour gérer les entrées comme 0.5d ou 0.7f qui sont correctement analysées par Int.parseInt (), mais ne devraient pas apparaître dans le champ de texte.


9
Woot? Depuis quand 0.5d est-il correctement analysé par Integer.parseInt ()?! Il lance une exception java.lang.NumberFormatException: Pour la chaîne d'entrée: "0.5d" (comme prévu, car ce n'est pas un entier)
Burkhard

4

Essayez ce code simple, il fera l'affaire.

DecimalFormat format = new DecimalFormat( "#.0" );
TextField field = new TextField();
field.setTextFormatter( new TextFormatter<>(c ->
{
    if ( c.getControlNewText().isEmpty() )
    {
        return c;
    }

    ParsePosition parsePosition = new ParsePosition( 0 );
    Object object = format.parse( c.getControlNewText(), parsePosition );

    if ( object == null || parsePosition.getIndex() <          c.getControlNewText().length() )
    {
        return null;
    }
    else
    {
        return c;
    }
}));

3

Si vous souhaitez appliquer le même écouteur à plusieurs TextField, voici la solution la plus simple:

TextField txtMinPrice, txtMaxPrice = new TextField();

ChangeListener<String> forceNumberListener = (observable, oldValue, newValue) -> {
    if (!newValue.matches("\\d*"))
      ((StringProperty) observable).set(oldValue);
};

txtMinPrice.textProperty().addListener(forceNumberListener);
txtMaxPrice.textProperty().addListener(forceNumberListener);

3

Celui-ci a fonctionné pour moi.

public void RestrictNumbersOnly(TextField tf){
    tf.textProperty().addListener(new ChangeListener<String>() {
        @Override
        public void changed(ObservableValue<? extends String> observable, String oldValue, 
            String newValue) {
            if (!newValue.matches("|[-\\+]?|[-\\+]?\\d+\\.?|[-\\+]?\\d+\\.?\\d+")){
                tf.setText(oldValue);
            }
        }
    });
}

3

Je veux aider avec mon idée de combiner la réponse Evan Knowles avec TextFormatterde JavaFX 8

textField.setTextFormatter(new TextFormatter<>(c -> {
    if (!c.getControlNewText().matches("\\d*")) 
        return null;
    else
        return c;
    }
));

donc bonne chance;) restez calme et codez java


2

Voici une classe simple qui gère quelques validations de base sur TextField, en utilisant TextFormatterintroduit dans JavaFX 8u40

ÉDITER:

(Code ajouté concernant le commentaire de Floern)

import java.text.DecimalFormatSymbols;
import java.util.regex.Pattern;

import javafx.beans.NamedArg;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TextFormatter.Change;

public class TextFieldValidator {

    private static final String CURRENCY_SYMBOL   = DecimalFormatSymbols.getInstance().getCurrencySymbol();
    private static final char   DECIMAL_SEPARATOR = DecimalFormatSymbols.getInstance().getDecimalSeparator();

    private final Pattern       INPUT_PATTERN;

    public TextFieldValidator(@NamedArg("modus") ValidationModus modus, @NamedArg("countOf") int countOf) {
        this(modus.createPattern(countOf));
    }

    public TextFieldValidator(@NamedArg("regex") String regex) {
        this(Pattern.compile(regex));
    }

    public TextFieldValidator(Pattern inputPattern) {
        INPUT_PATTERN = inputPattern;
    }

    public static TextFieldValidator maxFractionDigits(int countOf) {
        return new TextFieldValidator(maxFractionPattern(countOf));
    }

    public static TextFieldValidator maxIntegers(int countOf) {
        return new TextFieldValidator(maxIntegerPattern(countOf));
    }

    public static TextFieldValidator integersOnly() {
        return new TextFieldValidator(integersOnlyPattern());
    }

    public TextFormatter<Object> getFormatter() {
        return new TextFormatter<>(this::validateChange);
    }

    private Change validateChange(Change c) {
        if (validate(c.getControlNewText())) {
            return c;
        }
        return null;
    }

    public boolean validate(String input) {
        return INPUT_PATTERN.matcher(input).matches();
    }

    private static Pattern maxFractionPattern(int countOf) {
        return Pattern.compile("\\d*(\\" + DECIMAL_SEPARATOR + "\\d{0," + countOf + "})?");
    }

    private static Pattern maxCurrencyFractionPattern(int countOf) {
        return Pattern.compile("^\\" + CURRENCY_SYMBOL + "?\\s?\\d*(\\" + DECIMAL_SEPARATOR + "\\d{0," + countOf + "})?\\s?\\" +
                CURRENCY_SYMBOL + "?");
    }

    private static Pattern maxIntegerPattern(int countOf) {
        return Pattern.compile("\\d{0," + countOf + "}");
    }

    private static Pattern integersOnlyPattern() {
        return Pattern.compile("\\d*");
    }

    public enum ValidationModus {

        MAX_CURRENCY_FRACTION_DIGITS {
            @Override
            public Pattern createPattern(int countOf) {
                return maxCurrencyFractionPattern(countOf);
            }
        },

        MAX_FRACTION_DIGITS {
            @Override
            public Pattern createPattern(int countOf) {
                return maxFractionPattern(countOf);
            }
        },
        MAX_INTEGERS {
            @Override
            public Pattern createPattern(int countOf) {
                return maxIntegerPattern(countOf);
            }
        },

        INTEGERS_ONLY {
            @Override
            public Pattern createPattern(int countOf) {
                return integersOnlyPattern();
            }
        };

        public abstract Pattern createPattern(int countOf);
    }

}

Vous pouvez l'utiliser comme ceci:

textField.setTextFormatter(new TextFieldValidator(ValidationModus.INTEGERS_ONLY).getFormatter());

ou vous pouvez l'instancier dans un fichier fxml et l'appliquer à un customTextField avec les propriétés correspondantes.

app.fxml:

<fx:define>
    <TextFieldValidator fx:id="validator" modus="INTEGERS_ONLY"/>
</fx:define>

CustomTextField.class:

public class CustomTextField {

private TextField textField;

public CustomTextField(@NamedArg("validator") TextFieldValidator validator) {
        this();
        textField.setTextFormatter(validator.getFormatter());
    }
}

Code sur github


2

Voici ce que j'utilise:

private TextField textField;
textField.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
        if(!newValue.matches("[0-9]*")){
            textField.setText(oldValue);
        }

    }
});

La même chose en notation lambda serait:

private TextField textField;
textField.textProperty().addListener((observable, oldValue, newValue) -> {
    if(!newValue.matches("[0-9]*")){
        textField.setText(oldValue);
    }
});

2

Cette méthode permet à TextField de terminer tout le traitement (copier / coller / annuler en toute sécurité). Ne nécessite pas d'étendre les classes et vous permet de décider quoi faire avec le nouveau texte après chaque changement (pour le pousser à la logique, ou revenir à la valeur précédente, ou même pour le modifier).

  // fired by every text property change
textField.textProperty().addListener(
  (observable, oldValue, newValue) -> {
    // Your validation rules, anything you like
      // (! note 1 !) make sure that empty string (newValue.equals("")) 
      //   or initial text is always valid
      //   to prevent inifinity cycle
    // do whatever you want with newValue

    // If newValue is not valid for your rules
    ((StringProperty)observable).setValue(oldValue);
      // (! note 2 !) do not bind textProperty (textProperty().bind(someProperty))
      //   to anything in your code.  TextProperty implementation
      //   of StringProperty in TextFieldControl
      //   will throw RuntimeException in this case on setValue(string) call.
      //   Or catch and handle this exception.

    // If you want to change something in text
      // When it is valid for you with some changes that can be automated.
      // For example change it to upper case
    ((StringProperty)observable).setValue(newValue.toUpperCase());
  }
);

Pour votre cas, ajoutez simplement cette logique à l'intérieur. Fonctionne parfaitement.

   if (newValue.equals("")) return; 
   try {
     Integer i = Integer.valueOf(newValue);
     // do what you want with this i
   } catch (Exception e) {
     ((StringProperty)observable).setValue(oldValue);
   }

0

Mmmm. J'ai rencontré ce problème il y a des semaines. Comme l'API ne fournit pas de contrôle pour y parvenir,
vous pouvez utiliser le vôtre.
J'ai utilisé quelque chose comme:

public class IntegerBox extends TextBox {
    public-init var value : Integer = 0;
    protected function apply() {
        try {
            value = Integer.parseInt(text);
        } catch (e : NumberFormatException) {}
        text = "{value}";
    }
    override var focused = false on replace {apply()};
    override var action = function () {apply()}
}

Il est utilisé de la même manière qu'une normale TextBox,
mais possède également un valueattribut qui stocke l'entier saisi.
Lorsque le contrôle perd le focus, il valide la valeur et la rétablit (si elle n'est pas valide).


2
Quelle langue est-ce?
Stealth Rabbi

C'est JavaFX Script Rabbi, il est obsolète .
jewelsea

0

ce code Rendre votre texte Champ Accepter uniquement Numéro

textField.lengthProperty().addListener((observable, oldValue, newValue) -> {
        if(newValue.intValue() > oldValue.intValue()){
            char c = textField.getText().charAt(oldValue.intValue());
            /** Check if the new character is the number or other's */
            if( c > '9' || c < '0'){
                /** if it's not number then just setText to previous one */
                textField.setText(textField.getText().substring(0,textField.getText().length()-1));
            }
        }
    });

0

Ce code fonctionne très bien pour moi même si vous essayez de copier / coller.

myTextField.textProperty().addListener((observable, oldValue, newValue) -> {
    if (!newValue.matches("\\d*")) {
        myTextField.setText(oldValue);

    }
});

-1

Dans les mises à jour récentes de JavaFX, vous devez définir un nouveau texte dans la méthode Platform.runLater comme ceci:

    private void set_normal_number(TextField textField, String oldValue, String newValue) {
    try {
        int p = textField.getCaretPosition();
        if (!newValue.matches("\\d*")) {
            Platform.runLater(() -> {
                textField.setText(newValue.replaceAll("[^\\d]", ""));
                textField.positionCaret(p);
            });
        }
    } catch (Exception e) {
    }
}

C'est aussi une bonne idée de définir la position du curseur.


1
Merci pour votre réponse! Pourriez-vous expliquer un peu pourquoi Platform.runLaterest nécessaire?
TuringTux

@TuringTux dans la version récente de JavaFX, il lancera une exception si vous n'utilisez pas Platform.runLater
bdshahab

-1

Je voudrais améliorer la réponse d'Evan Knowles: https://stackoverflow.com/a/30796829/2628125

Dans mon cas, j'avais une classe avec des gestionnaires pour la partie UI Component. Initialisation:

this.dataText.textProperty().addListener((observable, oldValue, newValue) -> this.numericSanitization(observable, oldValue, newValue));

Et la méthode numbericSanitization:

private synchronized void numericSanitization(ObservableValue<? extends String> observable, String oldValue, String newValue) {
    final String allowedPattern = "\\d*";

    if (!newValue.matches(allowedPattern)) {
        this.dataText.setText(oldValue);
    }
}

Mot-clé synchronisé est ajouté pour éviter un éventuel problème de verrouillage de rendu dans javafx si setText sera appelé avant que l'ancien ne soit terminé. Il est facile à reproduire si vous commencez à taper très rapidement de mauvais caractères.

Un autre avantage est que vous ne conservez qu'un seul modèle pour correspondre et effectuez simplement une restauration. C'est mieux car vous pouvez facilement résumer la solution pour différents modèles de désinfection.


-1
rate_text.textProperty().addListener(new ChangeListener<String>() {

    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
        String s="";
        for(char c : newValue.toCharArray()){
            if(((int)c >= 48 && (int)c <= 57 || (int)c == 46)){
                s+=c;
            }
        }
        rate_text.setText(s);
    }
});

Cela fonctionne bien car cela vous permet de saisir uniquement une valeur entière et une valeur décimale (ayant le code ASCII 46).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.