La solita risposta a questo è "usa un DocumentListener
". Tuttavia, trovo sempre ingombrante quell'interfaccia. In verità l'interfaccia è troppo ingegnerizzata. Ha tre metodi, per l'inserimento, la rimozione e la sostituzione del testo, quando necessita di un solo metodo: la sostituzione. (Un inserimento può essere visualizzato come una sostituzione di un testo senza testo e una rimozione può essere vista come una sostituzione di un testo senza testo.)
Di solito tutto quello che vuoi sapere è quando il testo nella casella è cambiato , quindi DocumentListener
un'implementazione tipica ha i tre metodi che chiamano un metodo.
Pertanto ho creato il seguente metodo di utilità, che consente di utilizzare un metodo più semplice ChangeListener
anziché uno DocumentListener
. (Utilizza la sintassi lambda di Java 8, ma se necessario puoi adattarla alla vecchia Java.)
/**
* 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);
}
A differenza dell'aggiunta di un listener direttamente al documento, questo gestisce il caso (non comune) di installazione di un nuovo oggetto documento su un componente di testo. Inoltre, risolve il problema menzionato nella risposta di Jean-Marc Astesana , in cui il documento talvolta genera più eventi di quanti ne abbia bisogno.
Comunque, questo metodo ti consente di sostituire il codice fastidioso che assomiglia a questo:
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();
}
});
Con:
addChangeListener(someTextBox, e -> doSomething());
Codice rilasciato al pubblico dominio. Divertiti!