Изменение стоимости слушателя к компоненту jtextfield
Я хочу, чтобы окно сообщения появилось сразу после того, как пользователь изменит значение в текстовом поле. В настоящее время мне нужно нажать клавишу ввода, чтобы открыть окно сообщения. Что-то не так с моим кодом?
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);
}
}
}
любая помощь будет оценили!
11 ответов:
добавьте прослушиватель в базовый документ, который автоматически создается для вас.
// 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); } } });
обычный ответ на это "использовать
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());код выпущен в общественное достояние. Получайте удовольствие!
имейте в виду, что когда пользователь изменяет поле, DocumentListener может, когда-нибудь, получить два события. Например, если пользователь выбирает все содержимое поля, а затем нажимает клавишу, вы получите removeUpdate (все содержимое удаляется) и insertUpdate. В вашем случае, я не думаю, что это проблема, но, вообще говоря, это. К сожалению, кажется, что нет никакого способа отслеживать содержимое текстового поля без подкласса 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); } }
Я знаю, что это относится к действительно старой проблеме, однако, это вызвало у меня некоторые проблемы тоже. Как Клеопатра ответила в комментарии выше, я решил проблему с
JFormattedTextField. Однако решение требует немного больше работы, но аккуратнее.The
JFormattedTextFieldпо умолчанию не вызывает изменения свойств после каждого изменения текста в поле. Конструктор по умолчаниюJFormattedTextFieldне создает праматерии.однако, чтобы сделать то, что предложил ОП, вам нужно использовать форматер, который будет вызывать
commitEdit()метод после каждого допустимого редактирования поля. ЭлементcommitEdit()метод-это то, что вызывает изменение свойства из того, что я вижу, и без форматирования, это запускается по умолчанию при изменении фокуса или при нажатии клавиши enter.см http://docs.oracle.com/javase/tutorial/uiswing/components/formattedtextfield.html#value Для получения более подробной информации.
создать форматер по умолчанию (
DefaultFormatterобъект) для передачи вJFormattedTextFieldлибо через конструктор или сеттер-метод. Одним из методов форматирования по умолчанию являетсяsetCommitsOnValidEdit(boolean commit), который устанавливает форматер для запускаcommitEdit()метод каждый раз, когда текст изменяется. Это может быть подобран с помощьюPropertyChangeListenerиpropertyChange()метод.
просто создайте интерфейс, который расширяет DocumentListener и реализует все методы 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); } }и затем:
jTextField.getDocument().addDocumentListener(new SimpleDocumentListener() { @Override public void update(DocumentEvent e) { // Your code here } });или вы даже можете использовать лямбда-выражение:
jTextField.getDocument().addDocumentListener((SimpleDocumentListener) e -> { // Your code here });
вы можете использовать даже "MouseExited" для управления. пример:
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) { } }
Это была обновленная версия 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- это не пустые.
используйте KeyListener (который срабатывает на любой ключ), а не 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); } }кажется намного проще, чем здесь, и, кажется, работает, но, поскольку я пишу это, я бы рады услышать о каких-либо незамеченных проблем. Это проблема, что пользователь может ввести и оставить текстовое поле без внесения изменений? Я думаю, что все, что ты сделал-это ненужное задание.
DocumentFilter ? Это дает вам возможность манипулировать.
[ http://www.java2s.com/Tutorial/Java/0240__Swing/FormatJTextFieldstexttouppercase.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));
Comments