18 votes

Longueur maximale du champ TextField de JavaFX 2.2

Je travaille sur un projet JavaFX 2.2 et j'ai un problème avec l'utilisation de la fonction TextField contrôle. Je souhaite limiter le nombre de caractères qu'un utilisateur pourra saisir dans chaque champ de contrôle. TextField . Cependant, je n'arrive pas à trouver une propriété ou quelque chose comme longueur maximale . Le même problème se pose en Balançoire et a été résolue este manière. Comment résoudre ce problème pour JavaFX 2.2 ?

24voto

ceklock Points 1186

Il s'agit d'une meilleure façon d'effectuer le travail sur un champ de texte générique :

public static void addTextLimiter(final TextField tf, final int maxLength) {
    tf.textProperty().addListener(new ChangeListener<String>() {
        @Override
        public void changed(final ObservableValue<? extends String> ov, final String oldValue, final String newValue) {
            if (tf.getText().length() > maxLength) {
                String s = tf.getText().substring(0, maxLength);
                tf.setText(s);
            }
        }
    });
}

Fonctionne parfaitement, à l'exception du bug d'annulation.

18voto

kleopatra Points 31585

Avec java8u40, nous avons obtenu une nouvelle classe TextFormatter : l'une de ses principales responsabilités est de fournir un crochet pour toute modification de l'entrée de texte. avant il s'engage sur le contenu. Dans ce crochet, nous pouvons accepter/rejeter ou même de modifier la modification proposée.

L'exigence résolue dans le Réponse personnelle de l'OP es

  • la règle : limiter la longueur du texte à moins de n caractères
  • la modification : si la règle est violée, conserver les n derniers caractères comme texte d'entrée et supprimer les caractères excédentaires au début.

En utilisant un TextFormatter, cela pourrait être mis en œuvre comme suit :

// here we adjust the new text 
TextField adjust = new TextField("scrolling: " + len);
UnaryOperator<Change> modifyChange = c -> {
    if (c.isContentChange()) {
        int newLength = c.getControlNewText().length();
        if (newLength > len) {
            // replace the input text with the last len chars
            String tail = c.getControlNewText().substring(newLength - len, newLength);
            c.setText(tail);
            // replace the range to complete text
            // valid coordinates for range is in terms of old text
            int oldLength = c.getControlText().length();
            c.setRange(0, oldLength);
        }
    }
    return c;
};
adjust.setTextFormatter(new TextFormatter(modifyChange));

En marge :

  • la modification d'une propriété tout en écoutant son changement peut entraîner des effets secondaires inattendus
  • toutes les solutions proposées pour les événements au niveau des touches sont inefficaces (elles ne peuvent pas gérer les changements de collage/programmation)

8voto

Sergey Grinev Points 15565

Vous pouvez faire quelque chose de similaire à l'approche décrite ici : http://fxexperience.com/2012/02/restricting-input-on-a-textfield/

class LimitedTextField extends TextField {

    private final int limit;

    public LimitedTextField(int limit) {
        this.limit = limit;
    }

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

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

    private void verify() {
        if (getText().length() > limit) {
            setText(getText().substring(0, limit));
        }

    }
};

4voto

Le code complet que j'ai utilisé pour résoudre mon problème est le code ci-dessous. J'ai étendu la classe TextField comme Sergey Grinev l'a fait et j'ai ajouté un constructeur vide. Pour définir la longueur maximale, j'ai ajouté une méthode setter. Je vérifie d'abord et remplace ensuite le texte dans le champ TextField parce que je veux empêcher l'insertion de plus de caractères que la longueur maximale, sinon le caractère de longueur maximale + 1 sera inséré à la fin du champ TextField et le premier caractère du champ TextField sera supprimé.

package fx.mycontrols;

public class TextFieldLimited extends TextField {  
    private int maxlength;
    public TextFieldLimited() {
        this.maxlength = 10;
    }
    public void setMaxlength(int maxlength) {
        this.maxlength = maxlength;
    }
    @Override
    public void replaceText(int start, int end, String text) {
        // Delete or backspace user input.
        if (text.equals("")) {
            super.replaceText(start, end, text);
        } else if (getText().length() < maxlength) {
            super.replaceText(start, end, text);
        }
    }

    @Override
    public void replaceSelection(String text) {
        // Delete or backspace user input.
        if (text.equals("")) {
            super.replaceSelection(text);
        } else if (getText().length() < maxlength) {
            // Add characters, but don't exceed maxlength.
            if (text.length() > maxlength - getText().length()) {
                text = text.substring(0, maxlength- getText().length());
            }
            super.replaceSelection(text);
        }
    }
}

Dans le fichier fxml J'ai ajouté l'importation (du package dans lequel la classe TextFieldLimited existe) en haut du fichier et j'ai remplacé la balise TextField par le TextFieldLimited personnalisé.

<?import fx.mycontrols.*?>
.  
.  
. 
<TextFieldLimited fx:id="usernameTxtField" promptText="username" />

Dans la classe du contrôleur ,

en haut (déclaration de propriété),
@FXML
private TextFieldLimited usernameTxtField;

dans la méthode d'initialisation,
usernameTxtField.setLimit(40);

C'est tout.

2voto

hemisphire Points 694

J'utilise une méthode plus simple pour limiter le nombre de caractères et forcer la saisie numérique :

public TextField data;
public static final int maxLength = 5;

data.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable,
            String oldValue, String newValue) {
        try {
            // force numeric value by resetting to old value if exception is thrown
            Integer.parseInt(newValue);
            // force correct length by resetting to old value if longer than maxLength
            if(newValue.length() > maxLength)
                data.setText(oldValue);
        } catch (Exception e) {
            data.setText(oldValue);
        }
    }
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X