Die übliche Antwort darauf lautet "benutze a DocumentListener
". Ich finde diese Schnittstelle jedoch immer umständlich. Ehrlich gesagt ist die Schnittstelle überentwickelt. Es gibt drei Methoden zum Einfügen, Entfernen und Ersetzen von Text, wenn nur eine Methode erforderlich ist: Ersetzen. (Eine Einfügung kann als Ersatz für keinen Text durch Text angesehen werden, und ein Entfernen kann als Ersatz für Text ohne Text angesehen werden.)
Normalerweise möchten Sie nur wissen, wann sich der Text in der Box geändert hat. In einer typischen DocumentListener
Implementierung werden also drei Methoden verwendet, die eine Methode aufrufen.
Aus diesem Grund habe ich die folgende Dienstprogrammmethode erstellt, mit der Sie eine einfachere ChangeListener
als eine verwenden können DocumentListener
. (Es verwendet die Lambda-Syntax von Java 8, kann jedoch bei Bedarf an altes Java angepasst werden.)
/**
* 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);
}
Anders als beim direkten Hinzufügen eines Listeners zum Dokument wird hiermit der (ungewöhnliche) Fall behandelt, dass Sie ein neues Dokumentobjekt auf einer Textkomponente installieren. Darüber hinaus wird das in der Antwort von Jean-Marc Astesana erwähnte Problem umgangen , bei dem das Dokument manchmal mehr Ereignisse auslöst , als es benötigt.
Auf jeden Fall können Sie mit dieser Methode lästigen Code ersetzen, der folgendermaßen aussieht:
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();
}
});
Mit:
addChangeListener(someTextBox, e -> doSomething());
Code für die Öffentlichkeit freigegeben. Habe Spaß!