texto method inicial eventos change actualizar java swing listener jtextfield documentlistener

inicial - input method text change java



Value Change Listener to JTextField (11)

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 Massage", JOptionPane.ERROR_MESSAGE); } } });

Quiero que el cuadro de mensaje aparezca inmediatamente después de que el usuario cambie el valor en el campo de texto. Actualmente, necesito presionar la tecla Intro para que aparezca el cuadro de mensaje. ¿Hay algo mal 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 sería apreciada!


Fue la versión actualizada de Codemwnci. Su código es bastante bueno y funciona muy bien, excepto el mensaje de error. Para evitar errores debe cambiar la declaración 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); } } });


La respuesta habitual a esto es "usar un DocumentListener ". Sin embargo, siempre encuentro esa interfaz engorroso. Sinceramente, 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 se puede ver como un reemplazo de ningún texto con algún texto, y una eliminación se puede ver como un reemplazo de un texto sin texto).

Por lo general, todo lo que desea es saber cuándo ha cambiado el texto en el cuadro , por lo que una implementación típica de DocumentListener tiene los tres métodos que llaman a un método.

Por lo tanto, hice el siguiente método de utilidad, que te permite usar un ChangeListener más simple en lugar de un 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 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 de agregar un oyente directamente al documento, esto controla el caso (poco común) de que instale un nuevo objeto de documento en un componente de texto. Además, funciona alrededor del problema mencionado en la respuesta de Jean-Marc Astesana , donde el documento a veces dispara más eventos de los que necesita.

De todos modos, este método le permite reemplazar el 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 lanzado al dominio público. ¡Que te diviertas!


Puedes usar incluso "MouseExited" para controlar. 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) { } }


Sé que esto se relaciona con un problema realmente antiguo, sin embargo, también me causó algunos problemas. Como kleopatra respondió en un comentario anterior, resolví el problema con un JFormattedTextField . Sin embargo, la solución requiere un poco más de trabajo, pero es más ordenada.

El JFormattedTextField no JFormattedTextField de forma predeterminada un cambio de propiedad después de cada cambio de texto en el campo. El constructor predeterminado de JFormattedTextField no crea un formateador.

Sin embargo, para hacer lo que sugiere el OP, debe usar un formateador que invoque 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, esto se activa de forma predeterminada en un cambio de enfoque o cuando se presiona la tecla Intro.

Consulte http://docs.oracle.com/javase/tutorial/uiswing/components/formattedtextfield.html#value para obtener más detalles.

Cree un objeto de formateador predeterminado ( DefaultFormatter ) para pasarlo a JFormattedTextField a través de su constructor o mediante un método de establecimiento. Un método del formateador predeterminado es setCommitsOnValidEdit(boolean commit) , que configura al formateador para que active el método commitEdit() cada vez que se cambia el texto. Esto puede ser recogido usando un método PropertyChangeListener y propertyChange() .


Simplemente cree una interfaz que extienda 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 entonces:

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

o incluso puedes usar la expresión lambda:

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


Soy completamente nuevo en WindowBuilder y, de hecho, acabo de volver a Java después de unos años, pero implementé "algo", luego pensé que lo buscaría y encontré este hilo.

Estoy en medio de probar esto, así que, basado en 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 está aquí hasta ahora, y parece estar funcionando, pero, dado que estoy escribiendo esto, agradecería saber de cualquier error que se haya pasado por alto. ¿Es un problema que el usuario pueda ingresar y dejar el cuadro de texto sin hacer un cambio? Creo que todo lo que has hecho es una tarea innecesaria.


Tenga en cuenta que cuando el usuario modifica el campo, DocumentListener puede, en algún momento, recibir dos eventos. Por ejemplo, si el usuario selecciona todo el contenido del campo, luego presiona una tecla, recibirás un removeUpdate (se eliminará todo el contenido) y un insertUpdate. En su caso, no creo que sea un problema pero, en general, lo es. Desafortunadamente, parece que no hay manera de rastrear el contenido del campo de texto sin subclasificar 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); } }


Use un KeyListener (que se dispara en cualquier tecla) en lugar de ActionListener (que se dispara al entrar)


DocumentFilter ? Te da la habilidad de manipular.

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

Lo siento. 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));


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 no solo analizaría cualquier cosa que el usuario (tal vez en un accidente) toque en su teclado en un Integer . Debe capturar cualquier Exception lanzada y asegurarse de que el JTextField no esté vacío.