Вопрос

Я хочу, чтобы окно сообщения появилось сразу после того, как пользователь изменяет значение в текстовом поле. В настоящее время мне нужно нажать клавишу Enter, чтобы получить окно сообщения, чтобы выйти. Есть ли что-то не так с моим кодом?

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

Любая помощь будет оценена!

Это было полезно?

Решение

Добавьте слушателя в базовый документ, который автоматически создан для вас.

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

Другие советы

Обычный ответ на это «использовать DocumentListener«Однако я всегда нахожу этот интерфейс громоздкий. Правда Интерфейс переполнен. Он имеет три метода, для вставки, удаления и замены текста, когда ему нужен только один метод: замена. (Вставка может быть просмотрена как Замена без текста с некоторым текстом, и удаление можно просматривать как замена некоторых текста без текста.)

Обычно все, что вы хотите, состоит в том, чтобы знать Когда текст в коробке изменился, так что типичный DocumentListener Внедрение имеет три метода, вызывающими один метод.

Поэтому я сделал следующий метод утилиты, который позволяет вам использовать проще ChangeListener а не а. DocumentListener. Отказ (Он использует синтаксис лямбда Java 8, но вы можете адаптировать его для старой Java, если это необходимо.)

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

В отличие от добавления слушателя непосредственно в документ, это обрабатывает (необычный) случай, который вы устанавливаете новый объект документа на текстовом компоненте. Кроме того, он работает вокруг проблемы, упомянутой в Ответ Джин-Марка Астесана, где документ иногда стреляет больше событий, чем нужно.

В любом случае, этот метод позволяет заменить раздражающий код, который выглядит так:

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

Код выпущен к открытому доступу. Повеселись!

Помните, что, когда пользователь модифицирует поле, документальныйЛистенер может когда-нибудь получать два события. Например, если пользователь выбирает все содержимое поля, затем нажмите клавишу, вы получите RemoveUpdate (все содержимое удаляет) и inslipdate. В вашем случае я не думаю, что это проблема, но, вообще говоря, это. К сожалению, кажется, нет никакого способа отслеживать содержание текстового поля без подклассов jtextfield. Вот код класса, который предоставляет «текстовое» свойство:

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

Просто ящик интерфейса, который расширяет DocumentListener и реализует все методы документальногоListener:

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

а потом:

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

Или вы можете даже использовать выражение лямбда:

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

Я знаю, что это относится к действительно старой проблеме, однако это вызвало мне некоторые проблемы. Так как клеопатра ответил на комментарий выше, я решил проблему с JFormattedTextField. Отказ Тем не менее, решение требует немного больше работы, но является Neater.

То JFormattedTextField По умолчанию не вызывает изменение свойства после каждого изменения текста в поле. Конструктор по умолчанию JFormattedTextField не создает форматировать.

Однако делать то, что предложил ОП, вам нужно использовать Fixter, который будет вызывать commitEdit() Метод после каждого допустимого редактирования поля. То commitEdit() Метод - это то, что триггеры изменяются свойство от того, что я вижу, и без формата, это срабатывает по умолчанию при изменении фокуса или когда нажата клавиша ENTER.

Видеть http://docs.orcle.com/javase/tuTorial/uiswing/components/formattedtextfield.html#value. Больше подробностей.

Создайте форма по умолчанию (DefaultFormatter) объект, который будет передан в JFormattedTextField либо через его конструктор или метод сеттера. Один метод форматирования по умолчанию setCommitsOnValidEdit(boolean commit), что устанавливает Fixter для запуска commitEdit() Метод каждый раз, когда текст изменен. Это может быть подхвачено с помощью PropertyChangeListener и то propertyChange() метод.

Это была обновление версии CodeMwnci. Его код довольно хорошо и работает отлично, кроме сообщения об ошибке. Чтобы избежать ошибки необходимо изменить оператор условия.

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

Но я бы не просто разбирал что-нибудь, что пользователь (может быть, в аварии) касается его клавиатуры в Integer. Отказ Вы должны поймать любой Exceptions бросил и убедитесь, что JTextField не пусто.

Вы можете использовать даже «мышевые» для управления. пример:

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

        }

    }   

Используйте кейлистенер (который триггеры на любой клавише), а не на ActionListener (который триггеры в Enter)

Я совершенно новый в WindowBuilder, и, на самом деле, просто вернусь в Java через несколько лет, но я реализовал «что-то», потом подумал, что я посмотрю на это и наступил на эту нить.

Я в середине тестирования это, так, на основании нового для всего этого, я уверен, что я должен пропустить что-то.

Вот что я сделал, где «runtxt» - это текстовое поле, а «Runname» - это член элемента класса:

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

Кажется, намного проще, чем то, что здесь до сих пор, и, кажется, работает, но, поскольку я в середине написал это, я был бы признателен залым на любые упущенные готы. Это проблема, которую пользователь может ввести и оставить текстовое поле W / O, что делает изменения? Я думаю, что все, что вы сделали, это ненужное задание.

Если мы используем Runnable Method Handutivilities.invokelater () При использовании приложения слушателя документа иногда застряли и принимают время для обновления результата (согласно моему эксперименту). Вместо этого мы также можем использовать keyreleseed событие для текстового поля изменения слушателя, как уже упоминалось здесь.

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

DocumentFilter. ? Это дает вам возможность манипулировать.

[ http://www.java2s.com/tutorial/java/0240__swing/formatjtextfieldstexttouppercass.htm. ]

Извиняюсь. Я использую Jython (Python в Java) - но легко понять

# 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));
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top