Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Zeichen werden im JFormattedTextField überschrieben
Weiß jemand, wieso die Zeichen im JFormattedTextField überschrieben werden?
Wenn ich z.B. Folgendes habe:
Code:
JFormattedTextField jftf = new JFormattedTextField("qwertz");
Wenn ich das Programm ausführe und fange an vor dem "q" zu tippen, dann werden die Zeichen nacheinander überschrieben, als hätte ich auf die Taste [Einfg] gedrückt.
Gibt es eine Methode, um das zu unterbinden?
Das Problem tritt auch auf, wenn das Programm während der Laufzeit Text in das JFormattedTextField eingefügt hat.
Da ich mich etwas mit dem JFormattedTextField beschäftigt habe, möchte ich mal eine Antwort für andere Suchende geben (und vielleicht gibts ja von anderer Seite noch weitere Hinweise dazu?).
Dem JFormattedTextField kann bei der Initialisierung ein AbstractFormatter mitgegeben werden. Tut man dies nicht, so bekommt das JFormattedTextField automatisch den DefaultFormatter (javax.swing.text.DefaultFormatter).
Also:
Code:
javax.swing.JFormattedTextField ft = new javax.swing.JFormattedTextField(new javax.swing.text.DefaultFormatter());
Beim DefaultFormatter steht der Überschreibmodus standardmäßig auf true. Soll das Überschreiben unterbunden werden, muss man also Folgendes tun.
Code:
import javax.swing.*;
import javax.swing.text.*;
...
DefaultFormatter df = new DefaultFormatter();
df.setOverwriteMode(false); //Deakiviert den Überschreibmodus
JFormattedTextField ft = new JFormattedTextField(df);
Da getFormatter() nur AbstractFormatter zurückgibt, muss ein Casting ausgeführt werden, sonst kommt man nicht an die setOverwrite()-Methode. Statt mit dem DefaultFormatter kann natürlich auch ein anderer verwendet werden.
Mein eigenes Problem war/ist das Verhalten des JFormattedTextField, was das Begrenzen auf eine bestimmte Anzahl Stellen angeht.
Gebe ich dem JFormattedTextField einen NumberFormatter oder ein NumberFormat mit und begrenze die Stellen mit setMaximumIntegerDigits(), so funktioniert das zwar, allerdings können mehr Stellen eingeben werden, als mit setMaximumIntegerDigits() angeben - die Stellen die zuviel eingeben wurden, werden erst beim Verlassen des Feldes abgeschnitten. Außerdem können ebenfalls Buchstaben eingeben werden, die dann beim Verlassen des Feldes gelöscht werden.
Die Verwendung eines MaskFormatters habe ich genauso ausgeschlossen, da hierbei das Verhalten des Feldes m. E. nicht sehr schön ist. So kann man beliebig in des Feld hineinklicken und der Cursor steht dann dort, statt am Anfang des Feldes - auch wenn nichts im Feld drin steht. Dies liegt offensichtlich am Placeholder, der per Default ein Leerzeichen ist. Somit ist das Feld von vornherein mit diesem Platzhalter gefüllt und ich kann an jede Stelle in dem Feld klicken, an dem ein Leerzeichen steht.
Will ich bei einem JTextField die Anzahl der Stellen eingrenzen, so erweitere ich einfach das PlainDocument und überschreibe die Methode insertString(). Dort prüfe ich dann, ob der String länger ist als zugelassen, wenn nein, dann rufe ich super.insertString() auf, wenn ja, dann eben nicht. Genauso kann ich in insertString() prüfen, was ich als Eingabe zulassen möchte (Buchstaben, Zahlen usw.). Da insertString() bei jeder Eingabe im Feld aufgerufen wird, erfolgt die Prüfung auf Länge (oder Art) sofort und nicht erst nach Verlassen des Feldes. Mit setDocument() kann ich meinem JTextField dann mein erweitertes PlainDocument zuweisen.
Will ich das Gleiche beim JFormattedTextField machen, so habe ich ein Problem. Es funktioniert nicht. Zwar kann ich mit setDocument() mein erweitertes PlainDocument zuweisen, allerdings bleibt dies ohne Auswirkung. Dies liegt daran, dass beim JFormattedTextField der DefaultFormatter mit im Spiel ist. Dieser hat eine Methode getDocumentFiler() (protected), die immer den DefaultDocumentFilter zurückliefert. Irgendwann/Irgendwo wird diese Methode aufgerufen und mein erweitertes PlainDocument bekommt diesen DefaultDocumentFilter zugewiesen - denke ich zumindest. Und ist einem Document ein DocumentFilter zugewiesen, so laufen alle Aufrufe von insertString() über den Filer und meine insertString()-Methode in meinem erweiterten PlainDocument ist ohne Wirkung. Das explizite Setzen eines anderen Document Filters mit
Ich kann nur
1. Einen einen eigenen Formatter schreiben, indem ich z.B. den DefaultFormatter erweitere und die getDocumentFilter()-Methode überschreibe und meinen eigenen DocumentFilter zurückgebe
oder
2. In meinem erweiterten PlainDocument die Methode setDocumentFilter() überschreibe und dort ebenfalls meinen eigenen DocumentFilter weitergebe.
Erst dann habe ich ein Verhalten wie beim Textfeld.
Dabei stellt sich mir allerdings die Frage, für was ich dann noch das JFormattedTextField benötige und warum ich nicht gleich auf einem JTextField aufsetzen sollte und die nötige Funktionalität in meiner insertString() Methode hinterlege? Daneben muß ich zusätzlich noch darauf achten, dass ich beim JFormattedTextField getValue() und nicht getText() verwende, um auf den Inhalt des JFormattedTextField zuzugreifen (ist natürlich nicht zwingend notwendig). Dabei sollte die Methode commitEdit() nicht vergessen werden, mit der der Inhalt des JFormattedTextField nach value übertragen wird.
Also sind meine Fragen:
1. Hat jemand noch weitere interessante Erkenntnisse zum JFormattedTextField?
2. Wann ist es wirklich sinnvoll bzw. wann sollte man ein JFormattedTextField einem JTextField vorziehen?