Frage

Ich mag das Meldungsfeld sofort angezeigt werden, nachdem der Benutzer den Wert in dem Textfeld ändert. Derzeit muss ich die Enter-Taste drücken um das Meldungsfeld zu bekommen, um sie auszuwerfen. Gibt es etwas falsch mit meinem 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);
        }       
    }
}

Jede mögliche Hilfe würde geschätzt!

War es hilfreich?

Lösung

Fügen Sie einen Listener auf das darunter liegende Dokument, das automatisch für Sie erstellt wird.

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

Andere Tipps

Die übliche Antwort auf diese Frage ist „Verwendung ein DocumentListener “. Allerdings habe ich immer diese Schnittstelle umständlich finden. Wahrheits die Schnittstelle overengineered. Es verfügt über drei Methoden, zum Einsetzen, Entfernen und Ersetzen von Text, wenn es nur eine Methode benötigt: Ersatz. (Eine Insertion kann als Ersatz ohne Text mit Text angezeigt werden, und eine Entfernung kann ohne Text als Ersatz für etwas Text betrachtet werden.)

In der Regel alles, was Sie wollen, ist zu wissen, dass , wenn der Text in der Box hat sich geändert , so dass eine typische DocumentListener Implementierung hat die drei Methoden aufrufen ein Verfahren.

Deshalb habe ich die folgende Hilfsmethode, die können Sie verwenden, um eine einfachere ChangeListener eher als ein DocumentListener. (Es verwendet Java 8 der Lambda-Syntax, aber man kann es für alten Java anpassen, wenn nötig.)

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

Im Gegensatz zu einem Zuhörer direkt zu dem Dokument hinzufügen, diese Griffe des (seltene) Fall, dass Sie auf einer Textkomponente ein neues Dokument-Objekt installieren. Darüber hinaus arbeitet es um das genannte Problem in Jean-Marc Astesana Antwort , wo das Dokument manchmal mehr Ereignisse ausgelöst, als es muss.

Wie auch immer, diese Methode kann Sie lästigen Code ersetzen die aussieht wie folgt:

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

Mit:

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

Code Public Domain freigegeben. Viel Spaß!

Beachten Sie, dass, wenn der Benutzer das Feld ändern, kann die DocumentListener, irgendwann, erhalten zwei Veranstaltungen. Zum Beispiel, wenn der Benutzer den gesamten Feldinhalt, dann eine Taste drücken, erhalten Sie eine removeUpdate (alle Inhalte entfernen) und einen insertUpdate. In Ihrem Fall, ich glaube nicht, ist es ein Problem, aber im Allgemeinen ist es. Leider scheint es, gibt es keine Möglichkeit, ohne Subklassen JTextField den Inhalt des Textfield zu verfolgen. Hier ist der Code einer Klasse, die eine „Text“ Eigenschaft bieten:

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 Kiste eine Schnittstelle, die DocumentListener und implementiert alle DocumentListener Methoden erweitert:

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

und dann:

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

oder Sie können sogar Lambda-Ausdruck verwenden:

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

Ich weiß, dass dies zu einem wirklich alten Problem betrifft aber es hat mir einige zu Problemen. Wie kleopatra in einem Kommentar über reagierte, löste ich das Problem mit einem JFormattedTextField. Allerdings erfordert die Lösung ein bisschen mehr Arbeit, aber es ist ordentlicheres.

Die JFormattedTextField nicht standardmäßig Trigger eine Eigenschaftsänderung nach jeder Textänderungen im Feld. Der Standardkonstruktor von JFormattedTextField erstellt keinen Formatter.

Um jedoch zu tun, was der OP vorgeschlagen, benötigen Sie einen Formatierer verwenden, die die commitEdit() Methode nach jedem gültigen Bearbeiten des Feldes aufrufen wird. Die commitEdit() Methode ist es, was die Eigenschaftsänderung löst von dem, was ich sehe, und ohne die Formatierer kann dies standardmäßig auf einer Fokusänderung ausgelöst wird, oder wenn die Enter-Taste gedrückt wird.

Siehe http://docs.oracle.com/ JavaSE / tutorial / uiswing / components / formattedtextfield.html # Wert für weitere Details.

Erstellen Sie ein Standard-Formatierungsprogramm (DefaultFormatter) Objekt zum JFormattedTextField entweder über den Konstruktor oder eine Set-Methode übergeben werden. Ein Verfahren, die Standard-Formatierungs setCommitsOnValidEdit(boolean commit) ist, der den Formatierer setzt die Methode commitEdit() auszulösen jedesmal, wenn der Text geändert wird. Dies kann dann abgeholt wird mit einer PropertyChangeListener und der propertyChange() Methode.

war es die Update-Version von Codemwnci. sein Code ist recht gut und funktioniert gut, außer der Fehlermeldung. Um zu vermeiden, Fehler müssen Sie die Bedingungsanweisung ändern.

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

Aber ich würde nicht nur Parse etwas den Benutzer (vielleicht auf Unfall) berührt auf seiner Tastatur in ein Integer. Sie sollten alle Exceptions fangen geworfen und stellen Sie sicher, dass der JTextField leer ist, nicht.

Sie können mit sogar „MouseExited“ zu steuern. Beispiel:

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

        }

    }   

Verwenden Sie ein KeyListener (die Trigger auf einer beliebigen Taste) anstelle der Action (die Trigger für Eingabe)

Ich bin ganz neu in Windowbuilder, und in der Tat, nur immer wieder in Java nach ein paar Jahren, aber ich umgesetzt „etwas“, dann dachte ich, es aussehen würde und kam in diesem Thread.

Ich bin in der Mitte dieses zu testen, so auf dieser Basis für alle neuen zu sein, ich bin sicher, ich muss etwas fehlen.

Hier ist, was ich getan habe, wo „runTxt“ ein Textfeld und „runName“ ein Datum Mitglied der Klasse ist:

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

Es scheint viel einfacher als das, was hier so weit, und scheint zu funktionieren, aber da ich bin in der Mitte des Schreibens dieser, ich schätzt würde hören irgend gotchas übersehen. Ist es ein Problem, dass der Benutzer eingeben könnte und lassen Sie das Textfeld w / o eine Änderung vorzunehmen? Ich denke, dass alles, was Sie getan haben, ist eine unnötige Zuordnung.

Wenn wir verwenden runnable Methode SwingUtilities.invokeLater (), während Document Hörer Anwendung wird immer stecken manchmal und Zeit nehmen, um das Ergebnis zu aktualisieren (Stand meines Experiment). Anstatt dass wir auch keyReleased Ereignis für Textfeld Änderungsempfänger wie erwähnt verwenden hier .

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

DocumentFilter ? Es gibt Ihnen die Möglichkeit zu manipulieren.

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

Es tut uns leid. J sind mit Jython (Python in Java) - aber leicht zu verstehen,

# 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));
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top