JFormattedTextField-Inhalt wird auf neuen Wert aktualisiertJava

Java-Forum
Anonymous
 JFormattedTextField-Inhalt wird auf neuen Wert aktualisiert

Post by Anonymous »

Code: Select all

JFormattedTextFieldÜberraschenderweise aktualisiert 
den Feldtextinhalt beim Festschreiben des Werts nicht automatisch – es sei denn, ich fokussiere die Komponente neu (fokussiere etwas anderes und klicke dann erneut auf das Feld). Man könnte meinen, dass es OOB-Listener gibt, die das bereits tun.
Wie kann (sollte) ich dafür sorgen, dass das Feld seinen Wert direkt nach dem Festlegen widerspiegelt (auch wenn das Feld noch den Fokus behält)?
  • Code: Select all

    repaint()
    , revalidate() im Eigenschaften-Listener-Code haben keine Auswirkung.
  • Ich kann den Text manuell festlegen, aber es löst einen unnötigen Aufruf von stringToValue() aus, wodurch im Wesentlichen derselbe Wert noch einmal berechnet wird. Das ist nicht akzeptabel.
  • Ich habe auch festgestellt, dass das Zurücksetzen des Werts zwar funktioniert, für mich aber sehr hässlich aussieht. Für jeden Leser des Codes ist es bei weitem nicht offensichtlich, dass eine solch ungewöhnliche Zeile den Wert im Feld neu zeichnet (oder was sie überhaupt bewirkt). Außerdem setzt es das Caretzeichen auf Null – ich hingegen würde es vorziehen, wenn es dort bleibt, wo es ist (siehe Stack-Trace unten). Ich bin mir sicher, dass ich es anders machen soll.
Java 8.

Code: Select all

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

Code: Select all

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;
}
}
Nachdem Sie „Alex“ eingegeben und die Eingabetaste gedrückt haben:

Code: Select all

Value changed. New value: null
Value changed. New value: Person Alex
Image

Der Caret-Stack-Trace für Element 3:

Code: Select all

    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)

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post