Pregunta

Quiero el cuadro de mensaje que aparece inmediatamente después de que el usuario cambia el valor en el campo de texto. Actualmente, tengo que golpear la tecla Enter para obtener el cuadro de mensaje para que salga. ¿Hay mal cualquier cosa con mi código?

textField.addActionListener(new java.awt.event.ActionListener() {
    public void actionPerformed(java.awt.event.ActionEvent e) {

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

Cualquier ayuda se agradece!

¿Fue útil?

Solución

Añadir 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);
     }
  }
});

Otros consejos

La respuesta habitual a esto es "un uso DocumentListener ". Sin embargo, siempre me parece que engorroso interfaz. A decir verdad se-diseñado sobre la interfaz. Tiene tres métodos, para la inserción, eliminación y sustitución de texto, cuando sólo necesita un método: reemplazo. (Una inserción se puede ver como un reemplazo de ningún texto con un texto, y una eliminación puede ser vista como una sustitución de un texto sin texto.)

Por lo general, todo lo que quiere es saber es cuando el texto en el cuadro ha cambiado , por lo que una implementación típica DocumentListener tiene los tres métodos de llamada de un método.

Por lo tanto me hizo el siguiente método de utilidad, que le permite utilizar un simple ChangeListener en lugar de un DocumentListener. (Se utiliza la sintaxis lambda de Java 8, pero se puede adaptar para la edad de Java, 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 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 diferencia con la adición de un oyente directamente al documento, esta Trata el caso (poco común) que instale un nuevo objeto de documento en un componente de texto. Además, funciona en todo el problema mencionado en Jean-Marc de Astesana respuesta , donde el documento se dispara veces más eventos de lo que debe.

De todos modos, este método permite reemplazar código molesto, que es similar al siguiente:

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!

Tenga en cuenta que cuando el usuario modifique el campo, el DocumentListener puede, en algún momento, recibirá dos eventos. Por ejemplo, si el usuario selecciona todo el contenido del campo, a continuación, pulse una tecla, recibirá un removeUpdate (todo el contenido es quitar) y un insertUpdate. En su caso, no creo que es un problema, pero, en términos generales, lo es. Por desgracia, parece que no hay manera de rastrear el contenido de la textField sin la subclasificación JTextField. Aquí está el código de una clase que proporciona una propiedad de "texto":

package net.yapbam.gui.widget;

import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

/** A JTextField with a property that maps its text.
 * <br>I've found no way to track efficiently the modifications of the text of a JTextField ... so I developed this widget.
 * <br>DocumentListeners are intended to do it, unfortunately, when a text is replace in a field, the listener receive two events:<ol>
 * <li>One when the replaced text is removed.</li>
 * <li>One when the replacing text is inserted</li>
 * </ul>
 * The first event is ... simply absolutely misleading, it corresponds to a value that the text never had.
 * <br>Anoter problem with DocumentListener is that you can't modify the text into it (it throws IllegalStateException).
 * <br><br>Another way was to use KeyListeners ... but some key events are throw a long time (probably the key auto-repeat interval)
 * after the key was released. And others events (for example a click on an OK button) may occurs before the listener is informed of the change.
 * <br><br>This widget guarantees that no "ghost" property change is thrown !
 * @author Jean-Marc Astesana
 * <BR>License : GPL v3
 */

public class CoolJTextField extends JTextField {
    private static final long serialVersionUID = 1L;

    public static final String TEXT_PROPERTY = "text";

    public CoolJTextField() {
        this(0);
    }

    public CoolJTextField(int nbColumns) {
        super("", nbColumns);
        this.setDocument(new MyDocument());
    }

    @SuppressWarnings("serial")
    private class MyDocument extends PlainDocument {
        private boolean ignoreEvents = false;

        @Override
        public void replace(int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
            String oldValue = CoolJTextField.this.getText();
            this.ignoreEvents = true;
            super.replace(offset, length, text, attrs);
            this.ignoreEvents = false;
            String newValue = CoolJTextField.this.getText();
            if (!oldValue.equals(newValue)) CoolJTextField.this.firePropertyChange(TEXT_PROPERTY, oldValue, newValue);
        }

        @Override
        public void remove(int offs, int len) throws BadLocationException {
            String oldValue = CoolJTextField.this.getText();
            super.remove(offs, len);
            String newValue = CoolJTextField.this.getText();
            if (!ignoreEvents && !oldValue.equals(newValue)) CoolJTextField.this.firePropertyChange(TEXT_PROPERTY, oldValue, newValue);
        }
    }

Just cajón de una interfaz que se extiende DocumentListener e implementos todos los métodos 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, a continuación:

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

o incluso se puede usar la expresión lambda:

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

Sé que esto se refiere a un problema muy viejo, sin embargo, me causó algunos problemas también. Como kleopatra respondieron en un comentario anterior, he resuelto el problema con una JFormattedTextField. Sin embargo, la solución requiere un poco más de trabajo, pero es más ordenado.

El JFormattedTextField no lo hace por defecto de disparo de un cambio de propiedad después de cada cambio de texto en el campo. El constructor por defecto de JFormattedTextField no crea un formateador.

Sin embargo, hay que hacer lo que el PO sugiere, es necesario utilizar un formateador que invocará el método commitEdit() después de cada edición válida del campo. El método commitEdit() es lo que desencadena el cambio de propiedad de lo que puedo ver y sin el formateador, este se activa de forma predeterminada en un cambio de enfoque o cuando la tecla Enter se presiona.

http://docs.oracle.com/ JavaSE / tutorial / uiswing / componentes / formattedtextfield.html # valor para más detalles.

Crea un objeto formateador predeterminado (DefaultFormatter) que se pasa a la JFormattedTextField ya sea a través de su constructor o un método setter. Un método para el formateador predeterminado es setCommitsOnValidEdit(boolean commit), que establece el formateador para activar el método commitEdit() cada vez que se cambia el texto. Esto puede ser recogido usando una PropertyChangeListener y el método propertyChange().

era la versión de actualización de Codemwnci. su código es bastante fina y funciona muy bien, excepto el mensaje de error. Para evitar el error debe cambiar el estado de condición.

  // 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 (textField.getText().length()>0){
       JOptionPane.showMessageDialog(null,
          "Error: Please enter number bigger than 0", "Error Massage",
          JOptionPane.ERROR_MESSAGE);
     }
  }
});
textBoxName.getDocument().addDocumentListener(new DocumentListener() {
   @Override
   public void insertUpdate(DocumentEvent e) {
       onChange();
   }

   @Override
   public void removeUpdate(DocumentEvent e) {
      onChange();
   }

   @Override
   public void changedUpdate(DocumentEvent e) {
      onChange();
   } 
});

Pero lo haría no sólo nada de análisis del usuario (tal vez en accidente) toques en su teclado en un Integer. Usted debe coger cualquier Exceptions lanzados y asegurarse de que el JTextField no está vacío.

Se puede utilizar incluso "MouseExited" para el control. ejemplo:

 private void jtSoMauMouseExited(java.awt.event.MouseEvent evt) {                                    
        // TODO add your handling code here:
        try {
            if (Integer.parseInt(jtSoMau.getText()) > 1) {
                //auto update field
                SoMau = Integer.parseInt(jtSoMau.getText());
                int result = SoMau / 5;

                jtSoBlockQuan.setText(String.valueOf(result));
            }
        } catch (Exception e) {

        }

    }   

Utilice un KeyListener (que desencadena encima de las llaves) en lugar de la ActionListener (que disparadores de entrar)

Soy nuevo a WindowBuilder, y, de hecho, acaba de volver a meterse en Java después de algunos años, pero implementado "algo", entonces pensé en mirar hacia arriba y me encontré con este hilo.

Estoy en el medio de pruebas de esta, por lo que, sobre la base de ser nuevo en todo esto, estoy seguro de que debo estar perdiendo algo.

Esto es lo que hice, donde "runTxt" es un cuadro de texto y "runName" es un miembro de datos de la clase:

public void focusGained(FocusEvent e)
    {
    if (e.getSource() == runTxt)
        {
        System.out.println("runTxt got focus");
        runTxt.selectAll();
        }
    }
public void focusLost(FocusEvent e)
    {
    if (e.getSource() == runTxt)
        {
        System.out.println("runTxt lost focus");
        if(!runTxt.getText().equals(runName))runName= runTxt.getText();
        System.out.println("runText.getText()= " + runTxt.getText() + "; runName= " + runName);
        }
    }

Parece mucho más simple de lo que hay aquí hasta ahora, y parece estar funcionando, pero, desde que estoy en el medio de escribir esto, le agradecería la audición de cualquier pasado por alto aspectos críticos. Es un problema que el usuario podría entrar y salir del cuadro de texto w / o hacer un cambio? Creo que todo lo que has hecho es una tarea innecesaria.

Si usamos ejecutable SwingUtilities.invokeLater método () durante el uso de aplicación de escucha documento es conseguir veces atascados y tomar tiempo para actualizar el resultado (Según mi experimento). En lugar de que también podemos utilizar el evento para el cambio keyReleased campo de texto oyente como se mencionó aquí .

usernameTextField.addKeyListener(new KeyAdapter() {
        public void keyReleased(KeyEvent e) {
            JTextField textField = (JTextField) e.getSource();
            String text = textField.getText();
            textField.setText(text.toUpperCase());
        }
    });

DocumentFilter ? Se le da la capacidad de manipular.

[ http://www.java2s.com/Tutorial/Java/ 0240__Swing / FormatJTextFieldstexttouppercase.htm ]

Lo sentimos. J estoy usando Jython (Python en Java) - pero fácil de entender

# python style
# upper chars [ text.upper() ]

class myComboBoxEditorDocumentFilter( DocumentFilter ):
def __init__(self,jtext):
    self._jtext = jtext

def insertString(self,FilterBypass_fb, offset, text, AttributeSet_attrs):
    txt = self._jtext.getText()
    print('DocumentFilter-insertString:',offset,text,'old:',txt)
    FilterBypass_fb.insertString(offset, text.upper(), AttributeSet_attrs)

def replace(self,FilterBypass_fb, offset, length, text, AttributeSet_attrs):
    txt = self._jtext.getText()
    print('DocumentFilter-replace:',offset, length, text,'old:',txt)
    FilterBypass_fb.replace(offset, length, text.upper(), AttributeSet_attrs)

def remove(self,FilterBypass_fb, offset, length):
    txt = self._jtext.getText()
    print('DocumentFilter-remove:',offset, length, 'old:',txt)
    FilterBypass_fb.remove(offset, length)

// (java style ~example for ComboBox-jTextField)
cb = new ComboBox();
cb.setEditable( true );
cbEditor = cb.getEditor();
cbEditorComp = cbEditor.getEditorComponent();
cbEditorComp.getDocument().setDocumentFilter(new myComboBoxEditorDocumentFilter(cbEditorComp));
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top