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 ?
Réponses
Trop de publicités?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.
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)
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));
}
}
};
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.
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);
}
}
});
- Réponses précédentes
- Plus de réponses