La réponse habituelle à cela est "utiliser un DocumentListener
". Cependant, je trouve toujours cette interface encombrante. Vraiment, l'interface est sur-conçue. Il a trois méthodes, pour l'insertion, la suppression et le remplacement de texte, lorsqu'il n'a besoin que d'une seule méthode: le remplacement. (Une insertion peut être considérée comme un remplacement d'aucun texte par du texte et une suppression peut être considérée comme un remplacement d'un texte sans texte.)
Habituellement, tout ce que vous voulez, c'est savoir quand le texte dans la boîte a changé , donc une DocumentListener
implémentation typique a les trois méthodes appelant une méthode.
Par conséquent, j'ai créé la méthode utilitaire suivante, qui vous permet d'utiliser une méthode plus simple ChangeListener
que a DocumentListener
. (Il utilise la syntaxe lambda de Java 8, mais vous pouvez l'adapter pour l'ancien Java si nécessaire.)
/**
* Installs a listener to receive notification when the text of any
* {@code JTextComponent} is changed. Internally, it installs a
* {@link DocumentListener} on the text component's {@link Document},
* and a {@link PropertyChangeListener} on the text component to detect
* if the {@code Document} itself is replaced.
*
* @param text any text component, such as a {@link JTextField}
* or {@link JTextArea}
* @param changeListener a listener to receieve {@link ChangeEvent}s
* when the text is changed; the source object for the events
* will be the text component
* @throws NullPointerException if either parameter is null
*/
public static void addChangeListener(JTextComponent text, ChangeListener changeListener) {
Objects.requireNonNull(text);
Objects.requireNonNull(changeListener);
DocumentListener dl = new DocumentListener() {
private int lastChange = 0, lastNotifiedChange = 0;
@Override
public void insertUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void removeUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void changedUpdate(DocumentEvent e) {
lastChange++;
SwingUtilities.invokeLater(() -> {
if (lastNotifiedChange != lastChange) {
lastNotifiedChange = lastChange;
changeListener.stateChanged(new ChangeEvent(text));
}
});
}
};
text.addPropertyChangeListener("document", (PropertyChangeEvent e) -> {
Document d1 = (Document)e.getOldValue();
Document d2 = (Document)e.getNewValue();
if (d1 != null) d1.removeDocumentListener(dl);
if (d2 != null) d2.addDocumentListener(dl);
dl.changedUpdate(null);
});
Document d = text.getDocument();
if (d != null) d.addDocumentListener(dl);
}
Contrairement à l'ajout d'un écouteur directement au document, cela gère le cas (inhabituel) où vous installez un nouvel objet de document sur un composant de texte. De plus, il contourne le problème mentionné dans la réponse de Jean-Marc Astesana , où le document déclenche parfois plus d'événements qu'il n'en a besoin.
Quoi qu'il en soit, cette méthode vous permet de remplacer le code ennuyeux qui ressemble à ceci:
someTextBox.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
doSomething();
}
@Override
public void removeUpdate(DocumentEvent e) {
doSomething();
}
@Override
public void changedUpdate(DocumentEvent e) {
doSomething();
}
});
Avec:
addChangeListener(someTextBox, e -> doSomething());
Code rendu public. S'amuser!