Domanda

Voglio la finestra di messaggio appaia subito dopo che l'utente cambia il valore nel campo di testo. Attualmente, ho bisogno di colpire il tasto Invio per ottenere la finestra di messaggio a saltar fuori. C'è qualcosa di sbagliato con il mio codice?

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

Qualsiasi aiuto sarebbe apprezzato!

È stato utile?

Soluzione

Aggiungi un ascoltatore al Documento sottostante, che viene creato automaticamente per voi.

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

Altri suggerimenti

La solita risposta a questo è "l'uso di un DocumentListener ". Tuttavia, ho sempre trovato che ingombrante interfaccia. In verità l'interfaccia è sovra-ingegnerizzato. Ha tre metodi, per l'inserimento, la rimozione e la sostituzione di testo, quando è necessario un solo metodo: sostituzione. (Un inserimento può essere visto come una sostituzione di nessun testo con del testo, ed una rimozione può essere visto come una sostituzione di un testo senza testo.)

Di solito tutto quello che vuoi è sapere è quando il testo nella casella è cambiato , quindi una tipica implementazione DocumentListener ha tre metodi di chiamata di un metodo.

Quindi ho fatto la seguente metodo di utilità, che consente di utilizzare un semplice ChangeListener piuttosto che un DocumentListener. (Si utilizza la sintassi lambda di Java 8, ma è possibile adattarlo per il vecchio Java, se necessario.)

/**
 * 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 differenza con l'aggiunta di un ascoltatore direttamente al documento, Questo gestisce il (raro) caso che l'installazione di un nuovo oggetto documento su un componente di testo. Inoltre, funziona intorno al problema di cui Jean-Marc di Astesana risposta , in cui il documento a volte spara più eventi di quanto è necessario.

In ogni caso, questo metodo consente di sostituire il codice fastidioso che assomiglia a questo:

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

Codice rilasciato al pubblico dominio. Buon divertimento!

Si tenga presente che quando l'utente modificare il campo, il DocumentListener può, a volte, ricevere due eventi. Per esempio se l'utente seleziona l'intero contenuto campo, quindi premere un tasto, riceverai un removeUpdate (tutto il contenuto è la rimozione) ed un insertUpdate. Nel tuo caso, non credo che sia un problema, ma, in generale, lo è. Purtroppo, sembra che ci sia alcun modo per monitorare il contenuto del textField, senza sottoclasse JTextField. Ecco il codice di una classe che forniscono una proprietà "testo":

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

Proprio qui crea un interfaccia che si estende DocumentListener e implementa tutti i metodi 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);
    }
}

e poi:

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

o si può anche usare l'espressione lambda:

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

So che questo si riferisce ad un problema molto vecchio, però, mi ha causato anche qualche problema. Come kleopatra risposto in un commento sopra, ho risolto il problema con un JFormattedTextField. Tuttavia, la soluzione richiede un po 'più di lavoro, ma è più ordinato.

Il JFormattedTextField non lo fa da trigger di default un cambiamento proprietà dopo ogni modifiche al testo nel campo. Il costruttore di default di JFormattedTextField non crea un formattatore.

Tuttavia, per fare ciò che l'OP ha suggerito, è necessario utilizzare un formattatore che invocare il metodo commitEdit() dopo ogni modifica valida del campo. Il metodo commitEdit() è ciò che fa scattare il cambio di proprietà da quello che posso vedere e senza il formattatore, questo viene attivato per impostazione predefinita su un cambiamento di messa a fuoco o quando il tasto Invio viene premuto.

http://docs.oracle.com/ JavaSE / tutorial / uiswing / componenti / formattedtextfield.html # valore per ulteriori dettagli.

Creare un oggetto predefinito di formattazione (DefaultFormatter) da passare al JFormattedTextField sia tramite il suo costruttore o un metodo setter. Un metodo per il formattatore predefinito è setCommitsOnValidEdit(boolean commit), che imposta il formattatore per far scattare il metodo commitEdit() ogni volta che il testo viene modificato. Questo può quindi essere raccolto usando un PropertyChangeListener e il metodo propertyChange().

è stata la versione dell'aggiornamento del Codemwnci. il suo codice è abbastanza bene e funziona alla grande, tranne il messaggio di errore. Per evitare di errore è necessario modificare l'istruzione condizione.

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

Ma non sarebbe solo parse nulla l'utente (magari in incidenti) tocchi sulla sua tastiera in un Integer. Si dovrebbe prendere eventuali Exceptions gettati e assicurarsi che la JTextField non sia vuoto.

È possibile utilizzare anche "MouseExited" per il controllo. Esempio:

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

        }

    }   

Usa un KeyListener (che trigger su qualsiasi tasto), piuttosto che l'ActionListener (che trigger su Inserisci)

Sono nuovo di zecca WindowBuilder, e, di fatto, solo tornare in Java dopo un paio di anni, ma ho realizzato "qualcosa", allora ho pensato di guardare in su e sono imbattuto in questo thread.

Sono nel bel mezzo di prove, quindi, sulla base essendo nuovo a tutto questo, sono sicuro che io devo essere perso qualcosa.

Ecco quello che ho fatto, dove "runTxt" è una casella di testo e "runName" è un membro di dati della 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);
        }
    }

Sembra molto più semplice di quello che è qui finora, e sembra funzionare, ma, visto che sono nel bel mezzo della stesura di questo, mi farebbe piacere sentire di qualsiasi grattacapi trascurato. E 'un problema che l'utente potrebbe entrare e lasciare la casella di testo w / o fare un cambiamento? Credo che tutto quello che hai fatto è un compito inutile.

Se usiamo il metodo eseguibile SwingUtilities.invokeLater () durante l'utilizzo di applicazioni ascoltatore documento sta ottenendo a volte bloccati e prendendo tempo per aggiornare il risultato (Come per il mio esperimento). Invece di che possiamo anche usare evento KeyReleased per campo di testo il cambiamento ascoltatore come detto qui .

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

DocumentFilter ? Ti dà la possibilità di manipolare.

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

Siamo spiacenti. J sto usando Jython (Python in Java) - ma di facile comprensione

# 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));
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top