Question

Je veux la boîte de message apparaisse immédiatement après que l'utilisateur modifie la valeur dans le champ de texte. , Je dois actuellement frapper la touche Entrée pour obtenir la boîte de message à sortir. Y at-il quelque chose de mal avec mon code?

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

Toute aide serait appréciée!

Était-ce utile?

La solution

Ajouter un écouteur au document sous-jacent, qui est automatiquement créé pour vous.

// 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);
     }
  }
});

Autres conseils

La réponse habituelle à cette question est « l'utilisation d'un DocumentListener ». Cependant, je trouve toujours lourd d'interface. A vrai dire, l'interface est trop conçu. Il dispose de trois méthodes, pour l'insertion, le retrait et le remplacement du texte, quand il a besoin qu'une seule méthode: remplacement. (Une insertion peut être considérée comme un remplacement sans texte avec un texte et un retrait peut être considéré comme un remplacement d'un texte sans texte.)

En général, tout ce que vous voulez est de savoir est lorsque le texte dans la zone a changé , donc une implémentation DocumentListener typique a trois méthodes d'appel d'une méthode.

Par conséquent, je fait la méthode utilitaire suivante, qui vous permet d'utiliser un simple ChangeListener plutôt qu'un DocumentListener. (Il utilise la syntaxe lambda de Java 8, mais vous pouvez l'adapter pour le vieux Java si nécessaire.)

/**
 * 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);
}

Contrairement à l'ajout d'un auditeur directement au document, gère les (rares) cas que l'installation d'un nouvel objet de document sur un composant texte. En outre, il contourne le problème mentionné dans Jean-Marc réponse Astesana , où le document tire parfois plus d'événements que nécessaire.

Quoi qu'il en soit, cette méthode vous permet de remplacer le code ennuyeux qui ressemble à ceci:

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

addChangeListener(someTextBox, e -> doSomething());

code publié au domaine public. Amusez-vous bien!

Sachez que lorsque l'utilisateur modifie le champ, le DocumentListener peut, parfois, recevoir deux événements. Par exemple, si l'utilisateur sélectionne l'ensemble du contenu du champ, puis appuyez sur une touche, vous recevrez un removeUpdate (tout le contenu est remove) et un insertUpdate. Dans votre cas, je ne pense pas que ce soit un problème, mais, en général, il est. Malheureusement, il semble qu'il n'y a aucun moyen de suivre le contenu du textField sans sous-classement JTextField. Voici le code d'une classe qui fournit une propriété « texte »:

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

Juste une caisse interface qui étend DocumentListener et met en œuvre toutes les méthodes 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);
    }
}

et

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

ou vous pouvez même utiliser l'expression lambda:

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

Je sais que cela se rapporte à un problème vraiment vieux, cependant, il m'a causé quelques problèmes aussi. Comme kleopatra a répondu dans un commentaire ci-dessus, je résolu le problème avec un JFormattedTextField. Cependant, la solution nécessite un peu plus de travail, mais il est plus propre.

Le JFormattedTextField ne par défaut déclencheur d'un changement de propriété après tous les changements de texte dans le champ. Le constructeur par défaut de JFormattedTextField ne crée pas de formatter.

Cependant, pour faire ce que l'OP a suggéré, vous devez utiliser un formateur qui appelle la méthode commitEdit() après chaque modification valide du champ. La méthode de commitEdit() est ce qui déclenche le changement de propriété de ce que je peux voir et sans formatter, cela est déclenché par défaut sur un changement de mise au point ou lorsque la touche entrée est enfoncée.

Voir http://docs.oracle.com/ JavaSE / tutorial / uiswing / composants / formattedtextfield.html # valeur pour plus de détails.

Créer un objet à transmettre à la DefaultFormatter soit par son constructeur ou une méthode de définition de mise en forme par défaut (JFormattedTextField). Une méthode de la mise en forme par défaut est setCommitsOnValidEdit(boolean commit), qui fixe le formatter pour déclencher la méthode commitEdit() chaque fois que le texte est modifié. Cela peut ensuite être repris à l'aide d'un PropertyChangeListener et la méthode propertyChange().

il était la version de mise à jour Codemwnci. son code est très bien et fonctionne très bien, sauf le message d'erreur. Pour éviter d'erreur, vous devez modifier l'instruction de condition.

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

Mais je ne voudrais pas que quoi que ce soit parse l'utilisateur (peut-être sur un accident) touche sur son clavier dans un Integer. Vous devez attraper tous les Exceptions jetés et assurez-vous que le JTextField est pas vide.

Vous pouvez même utiliser « MouseExited » pour le contrôle. exemple:

 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) {

        }

    }   

Utiliser un KeyListener (qui déclenche sur une touche) plutôt que le ActionListener (qui déclenche à entrer)

Je suis tout nouveau à WindowBuilder, et, en fait, juste revenir en Java après quelques années, mais je mis en œuvre « quelque chose », alors pensé que je regarde vers le haut et suis tombé sur ce fil.

Je suis au milieu de ce test, donc, sur la base d'être nouveau à tout cela, je suis sûr que je dois manquer quelque chose.

Voici ce que je faisais, où « runTxt » est une zone de texte et « runName » est membre de données de la classe:

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

Il semble beaucoup plus simple que ce qui est ici jusqu'à présent, et semble fonctionner, mais, depuis que je suis en train d'écrire, je serais heureux d'entendre de tout négligé gotchas. Est-ce un problème que l'utilisateur puisse entrer et sortir de la zone de texte w / o faire un changement? Je pense que tout ce que vous avez fait est une tâche inutile.

Si nous utilisons la méthode runnable SwingUtilities.invokeLater () en utilisant l'application de l'écouteur document est coincé et obtenir parfois de prendre le temps de mettre à jour le résultat (Selon mon expérience). Au lieu de cela, nous pouvons également utiliser l'événement KeyReleased pour modifier un champ de texte d'écoute comme mentionné ici .

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

DocumentFilter ? Il vous donne la possibilité de manipuler.

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

Désolé. J utilise Jython am (Python en Java) - mais facile à comprendre

# 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));
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top