Обновление содержимого JFormattedTextField по новому значениюJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Обновление содержимого JFormattedTextField по новому значению

Сообщение Anonymous »

JFormattedTextField, что удивительно, не обновляет автоматически текстовое содержимое поля при фиксации значения — если только я не перефокусирую компонент (сфокусирую его на чем-то другом, а затем снова щелкну по полю). Можно было бы подумать, что есть прослушиватели OOB, которые уже это делают.
Как мне (должно) заставить поле отражать свое значение сразу после его установки (даже если поле все еще удерживает фокус)?
  • repaint(), revalidate() в коде прослушивателя свойств не имеют никакого эффекта.
  • Я могу установить текст вручную, но это вызовет ненужный вызов stringToValue(), по сути вычисляя одно и то же значение заново. Это неприемлемо.
  • Я также обнаружил, что сброс значения работает, но на мой взгляд выглядит очень некрасиво. Для любого читателя кода далеко не очевидно, что такая необычная строка перерисовывает значение в поле (или что она вообще делает). Кроме того, он устанавливает курсор на ноль — я, с другой стороны, предпочел бы, чтобы он оставался там, где он есть (см. трассировку стека внизу). Я уверен, что нужно сделать это по-другому.
Java 8.
import javax.swing.JFormattedTextField;
import javax.swing.JFormattedTextField.AbstractFormatter;
import javax.swing.JFormattedTextField.AbstractFormatterFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
import javax.swing.text.DefaultFormatter;
import javax.swing.text.DefaultFormatterFactory;
import java.awt.Component;
import java.awt.Container;

public class FormattedTextFieldDemo {

public static void main(String[] args) {
JFrame frame = new JFrame("Formatted Text Field Demo");
frame.setContentPane(createMainPanel());
frame.setLocationRelativeTo(null);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}

private static Container createMainPanel() {
JPanel panel = new JPanel();
panel.add(createTextField());
return panel;
}

private static Component createTextField() {
JFormattedTextField field = new JFormattedTextField();
field.setColumns(10);
field.setFormatterFactory(createFormatterFactory());
field.addPropertyChangeListener("value", e -> {
// 1. useless
// field.repaint();

// 2. works but triggers superfluous value computation
// field.setText(toString((Person) e.getNewValue()));

// 3. works but ugly (the equals() check is to avoid StackOverflowError)
// if (!Objects.equals(e.getOldValue(), e.getNewValue())) field.setValue(field.getValue());
System.out.printf("Value changed. New value: %s\n", e.getNewValue());
});
return field;
}

private static AbstractFormatterFactory createFormatterFactory() {
DefaultFormatterFactory formatterFactory = new DefaultFormatterFactory();
formatterFactory.setDefaultFormatter(createFormatter());
return formatterFactory;
}

private static AbstractFormatter createFormatter() {
AbstractFormatter formatter = new DefaultFormatter() {
@Override
public Object stringToValue(String string) {
return (string == null) ? null : new Person(string);
}

@Override
public String valueToString(Object value) {
return (value instanceof Person) ? FormattedTextFieldDemo.toString((Person) value) : null;
}
};
return formatter;
}

private static String toString(Person value) {
if (value == null) return null;
return String.format("Person %s", value.getName());
}
}

public class Person {

private String name;

public Person(String name) {
this.name = name;
}

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

@Override
public String toString() {
return "Person " + name;
}
}

После ввода «Алекс» и нажатия Enter:
Value changed. New value: null
Value changed. New value: Person Alex


Изображение

Трассировка стека курсоров для элемента 3:
at javax.swing.text.DefaultCaret.setDot(DefaultCaret.java:1051)
at javax.swing.text.JTextComponent.setCaretPosition(JTextComponent.java:1631)
at javax.swing.text.DefaultFormatter.positionCursorAtInitialLocation(DefaultFormatter.java:333)
at javax.swing.text.DefaultFormatter.install(DefaultFormatter.java:126)
at javax.swing.JFormattedTextField.setFormatter(JFormattedTextField.java:464)
at javax.swing.JFormattedTextField.setValue(JFormattedTextField.java:788)
at javax.swing.JFormattedTextField.setValue(JFormattedTextField.java:501)
at demos.text.field.FormattedTextFieldDemo.lambda$createTextField$0(FormattedTextFieldDemo.java:39)


Подробнее здесь: https://stackoverflow.com/questions/798 ... -new-value
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»