Valeur Changeur Listener à JTextField

Je souhaite que la boîte de message apparaisse immédiatement après que l’utilisateur a modifié la valeur dans le champ de texte. Actuellement, je dois appuyer sur la touche Entrée pour faire apparaître la boîte de message. Y a-t-il quelque chose qui cloche 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!

Ajoutez un écouteur au document sous-jacent, créé automatiquement 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 Massage", JOptionPane.ERROR_MESSAGE); } } }); 

La réponse habituelle à ceci est “utiliser un DocumentListener “. Cependant, je trouve toujours que cette interface est encombrante. En vérité, l’interface est sur-conçue. Il a trois méthodes pour l’insertion, le retrait et le remplacement du texte, lorsqu’il ne nécessite qu’une méthode: le remplacement. (Une insertion peut être considérée comme un remplacement d’aucun texte avec du texte, et une suppression peut être considérée comme un remplacement de texte sans texte.)

Généralement, tout ce que vous voulez savoir, c’est lorsque le texte de la boîte a changé , de sorte qu’une implémentation DocumentListener classique utilise les trois méthodes appelant une méthode.

Par conséquent, j’ai utilisé la méthode d’utilitaire suivante, qui vous permet d’utiliser un ChangeListener plus simple que DocumentListener . (Il utilise la syntaxe lambda de Java 8, mais vous pouvez l’adapter pour l’ancien 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 écouteur directement au document, cela gère le cas (inhabituel) d’installation d’un nouvel object de document sur un composant de texte. De plus, cela fonctionne autour du problème mentionné dans la réponse de Jean-Marc Astesana , où le document déclenche parfois plus d’événements qu’il n’est 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(); } }); 

Avec:

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

Code publié dans le domaine public. S’amuser!

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

 package net.yapbam.gui.widget; import javax.swing.JTextField; import javax.swing.text.AtsortingbuteSet; import javax.swing.text.BadLocationException; import javax.swing.text.PlainDocument; /** A JTextField with a property that maps its text. * 
I've found no way to track efficiently the modifications of the text of a JTextField ... so I developed this widget. *
DocumentListeners are intended to do it, unfortunately, when a text is replace in a field, the listener receive two events:
    *
  1. One when the replaced text is removed.
  2. *
  3. One when the replacing text is inserted
  4. * * The first event is ... simply absolutely misleading, it corresponds to a value that the text never had. *
    Anoter problem with DocumentListener is that you can't modify the text into it (it throws IllegalStateException). *

    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. *

    This widget guarantees that no "ghost" property change is thrown ! * @author Jean-Marc Astesana *
    License : GPL v3 */ public class CoolJTextField extends JTextField { private static final long serialVersionUID = 1L; public static final Ssortingng 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, Ssortingng text, AtsortingbuteSet attrs) throws BadLocationException { Ssortingng oldValue = CoolJTextField.this.getText(); this.ignoreEvents = true; super.replace(offset, length, text, attrs); this.ignoreEvents = false; Ssortingng 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 { Ssortingng oldValue = CoolJTextField.this.getText(); super.remove(offs, len); Ssortingng newValue = CoolJTextField.this.getText(); if (!ignoreEvents && !oldValue.equals(newValue)) CoolJTextField.this.firePropertyChange(TEXT_PROPERTY, oldValue, newValue); } }

Je sais que cela est lié à un problème très ancien, mais cela m’a causé des problèmes. Comme kleopatra a répondu dans un commentaire ci-dessus, j’ai résolu le problème avec un JFormattedTextField . Cependant, la solution nécessite un peu plus de travail, mais elle est plus propre.

JFormattedTextField ne déclenche pas par défaut une modification de propriété après chaque modification de texte dans le champ. Le constructeur par défaut de JFormattedTextField ne crée pas de formateur.

Cependant, pour faire ce que l’OP suggère, vous devez utiliser un formateur qui invoquera la méthode commitEdit() après chaque édition valide du champ. La méthode commitEdit() est ce qui déclenche le changement de propriété par rapport à ce que je peux voir et sans le formateur, celui-ci est déclenché par défaut lors d’un changement de focus ou lorsque la touche Entrée est enfoncée.

Voir http://docs.oracle.com/javase/tutorial/uiswing/components/formattedtextfield.html#value pour plus de détails.

Créez un object de formatage par défaut ( DefaultFormatter ) à transmettre à JFormattedTextField via son constructeur ou une méthode de JFormattedTextField . Une méthode du formateur par défaut est setCommitsOnValidEdit(boolean commit) , qui définit le formateur pour qu’il déclenche la méthode commitEdit() chaque fois que le texte est modifié. Cela peut être récupéré en utilisant la méthode PropertyChangeListener et la méthode propertyChange() .

Créez simplement une interface qui étend DocumentListener et implémente toutes les méthodes 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 alors:

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

Vous pouvez même utiliser “MouseExited” pour contrôler. 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(Ssortingng.valueOf(result)); } } catch (Exception e) { } } 

c’était la version de mise à jour de Codemwnci. son code est très bon et fonctionne très bien sauf le message d’erreur. Pour éviter toute 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 ferais pas qu’parsingr tout ce que l’utilisateur (peut-être par accident) touche à son clavier en un Integer . Vous devez intercepter toutes les Exception JTextField et vous assurer que JTextField n’est pas vide.

Utilisez un KeyListener (qui se déclenche sur n’importe quelle touche) plutôt que le ActionListener (qui se déclenche lors de la saisie)

Je suis tout nouveau sur WindowBuilder et, en fait, je reviens à Java après quelques années, mais j’ai implémenté “quelque chose”, puis j’ai pensé que je le chercherais et que je trouverais ce sujet.

Je suis en train de tester cela, donc, étant nouveau dans tout cela, je suis sûr que je dois rater quelque chose.

Voici ce que j’ai fait, où “runTxt” est une zone de texte et “runName” est un 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); } } 

Cela semble beaucoup plus simple que ce qui se passe ici et semble fonctionner, mais, étant donné que je suis en train d’écrire cela, je serais heureux d’entendre parler de tout piège négligé. Est-ce un problème que l’utilisateur puisse entrer et sortir de la zone de texte sans faire de changement? Je pense que tout ce que vous avez fait est une tâche inutile.

DocumentFilter ? Cela vous donne la possibilité de manipuler.

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

Pardon. J utilise Jython (Python en Java) – mais facile à comprendre

 # python style # upper chars [ text.upper() ] class myComboBoxEditorDocumentFilter( DocumentFilter ): def __init__(self,jtext): self._jtext = jtext def insertSsortingng(self,FilterBypass_fb, offset, text, AtsortingbuteSet_attrs): txt = self._jtext.getText() print('DocumentFilter-insertSsortingng:',offset,text,'old:',txt) FilterBypass_fb.insertSsortingng(offset, text.upper(), AtsortingbuteSet_attrs) def replace(self,FilterBypass_fb, offset, length, text, AtsortingbuteSet_attrs): txt = self._jtext.getText() print('DocumentFilter-replace:',offset, length, text,'old:',txt) FilterBypass_fb.replace(offset, length, text.upper(), AtsortingbuteSet_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));