Saltar al contenido

Oyente de cambio de valor a JTextField

El paso a paso o código que encontrarás en este post es la solución más rápida y efectiva que hallamos a esta duda o problema.

Solución:

Agregue un oyente al documento subyacente, que se crea automáticamente para usted.

// Listen for changes in the text
textField.getDocument().addDocumentListener(new DocumentListener() 
  public void changedUpdate(DocumentEvent e) 
    warn();
  
  public void removeUpdate(DocumentEvent e) 
    warn();
  
  public void insertUpdate(DocumentEvent e) 
    warn();
  

  public void warn() 
     if (Integer.parseInt(textField.getText())<=0)
       JOptionPane.showMessageDialog(null,
          "Error: Please enter number bigger than 0", "Error Message",
          JOptionPane.ERROR_MESSAGE);
     
  
);

La respuesta habitual a esto es "utilice un DocumentListener". Sin embargo, siempre encuentro esa interfaz engorrosa. A decir verdad, la interfaz está sobre-diseñada. Tiene tres métodos, para la inserción, eliminación y reemplazo de texto, cuando solo necesita un método: reemplazo. (Una inserción puede verse como un reemplazo de ningún texto con un texto, y una eliminación puede verse como un reemplazo de un texto sin texto).

Por lo general, todo lo que quieres es saber cuando el texto en el cuadro ha cambiado, tan típico DocumentListener La implementación tiene los tres métodos que llaman a un método.

Por lo tanto, hice el siguiente método de utilidad, que le permite usar un método más simple. ChangeListener preferible a DocumentListener. (Utiliza la sintaxis lambda de Java 8, pero puede adaptarla para Java antiguo si es necesario).

/**
 * 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 ChangeEvents
 *        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 diferencia de agregar un oyente directamente al documento, esto maneja el caso (poco común) de que instale un nuevo objeto de documento en un componente de texto. Además, soluciona el problema mencionado en la respuesta de Jean-Marc Astesana, donde el documento a veces desencadena más eventos de los necesarios.

De todos modos, este método te permite reemplazar un código molesto que se ve así:

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());

Código liberado al dominio público. ¡Divertirse!

Simplemente cree una interfaz que amplíe DocumentListener e implemente todos los métodos de DocumentListener:

@FunctionalInterface
public interface SimpleDocumentListener extends DocumentListener 
    void update(DocumentEvent e);

    @Override
    default void insertUpdate(DocumentEvent e) 
        update(e);
    
    @Override
    default void removeUpdate(DocumentEvent e) 
        update(e);
    
    @Override
    default void changedUpdate(DocumentEvent e) 
        update(e);
    

y luego:

jTextField.getDocument().addDocumentListener(new SimpleDocumentListener() 
    @Override
    public void update(DocumentEvent e) 
        // Your code here
    
);

o incluso puede usar la expresión lambda:

jTextField.getDocument().addDocumentListener((SimpleDocumentListener) e -> 
    // Your code here
);

Te mostramos las reseñas y valoraciones de los lectores

Agradecemos que quieras ayudar nuestro trabajo añadiendo un comentario y dejando una puntuación te estamos agradecidos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *