Swing JTextField mit DocumentFilter

  • Themenstarter Themenstarter Camino
  • Beginndatum Beginndatum
C

Camino

Gast
Hallo,

ich hab in einem Dialog Textfelder, bei denen ich eine Zeichenbegrenzung erreichen möchte, sowohl die Zeichenanzahl als auch die erlaubten Zeichen. Da es sich um Textfelder für Nach- und Vornamen handelt, sollten nur für Namen zulässige Zeichen eingegeben werden können. Ich hab im Internet ein Beispiel mit einem DocumentFilter gefunden, dass leider noch nicht ganz funktioniert:
Java:
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;

/**
 * Filter für Textfelder für bestimmte Zeichenlänge und Muster
 * @param maxChars maximal zulässige Zeichenlänge
 * @param pattern Muster für Texteingabe
 */
public class DocumentSizeFilter
extends DocumentFilter {
	
	public static final String TEXT_PATTERN = "[A-Za-zßé-]+";

	private final int maxCharacters;
	private final String pattern;
	    

	public DocumentSizeFilter( final int maxChars, final String pattern ) {
		maxCharacters = maxChars;
		this.pattern = pattern;
	}

	
	@Override
    public void replace( FilterBypass fb, int offs, int length, String str, AttributeSet a )
            throws BadLocationException {
		
        if ( str.matches( pattern ) && ( fb.getDocument().getLength() + str.length() - length ) <= maxCharacters ) {
            super.replace( fb, offs, length, str, a );
        }
        
    }

}

In meinem Dialog sehen die Textfelder so aus:
Java:
...
JTextField tfVorname = new JTextField();
tfVorname.setPreferredSize(new Dimension( 250, tfZeilenhoehe ));
tfVorname.getDocument().addDocumentListener( new PersonDocumentListener( this ) );
tfVorname.addKeyListener( tfKeyListener );
( ( AbstractDocument ) tfVorname.getDocument()).setDocumentFilter( new DocumentSizeFilter( 100, DocumentSizeFilter.TEXT_PATTERN ) );
...
Der PersonDocumentListener filtert eine Tabelle mit Personeneinträgen, wenn sich im Textfeld was geändert hat. Den KeyListener benutze ich, um die ENTER-Taste abzufangen. Mir geht es hier aber um den DocumentFIlter, der bei dem Textfeld gesetzt wird. Es wird ein neuer DocumentSizeFilter erstellt, und die maximale Zeichenanzahl und das Pattern übergeben.

OK, nun habe ich damit 2 Probleme:

1.) Ich hab das Pattern "[A-Za-zßé-]+". Vorher war es nur "[A-Za-z]+" und ich hab es erstmal um die Zeichen "ßé-" ergänzt. Da müssen aber wohl noch weitere Zeichen rein, die in Namen vorkommen können. Gibt es da schon ein Pattern als Vorgabe, welches möglichst alle Zeichen für Wörter wie Namen einschliesst, also ohne Ziffern oder Sonderzeichen? Oder eine andere bessere Lösung? Wie bekomme ich das Leerzeichen mit in das Pattern rein? Es gibt ja auch Nachnamen mit Leerzeichen, oder mehrere Vornamen. Bei der jetzigen Lösung werden keine Leerzeichen akzeptiert.

2.) In meinem Dialog hab ich auch einen Button "Zurücksetzen", welcher die Textfelder wieder leeren soll. Seit ich den DocumentFilter eingebunden habe, klappt das aber nicht mehr. Die Textfelder werden nicht zurückgesetzt (geleert). Auf dem Button liegt ein ActionListener, welcher beim klicken folgendes ausführt:
Java:
if (e.getActionCommand().equals("Zurücksetzen")) {
	tfNachname.setText("");
	tfVorname.setText("");
	tfMatrikelnummer.setText("");
}

Würde mich freuen, wenn mir wer bei meinen Problemen helfen könnte.

Camino
 
OK, nun habe ich damit 2 Probleme:

1.) Wie bekomme ich das Leerzeichen mit in das Pattern rein? Es gibt ja auch Nachnamen mit Leerzeichen, oder mehrere Vornamen. Bei der jetzigen Lösung werden keine Leerzeichen akzeptiert.
Einfach vorne mit rein setzen? -> "[ A-Za-zßé-]+"
Obs da schon ein vernünftiges Pattern gibt? Von Haus aus sicherlich nicht, im Internet generell? Bestimmt ist irgendwo etwas zu finden. Vllt. wäre es leichter einen bestimmten ASCII Bereich zu filtern, anstelle einzelne Zeichen aufzuzählen ?! :bahnhof:
2.) In meinem Dialog hab ich auch einen Button "Zurücksetzen", welcher die Textfelder wieder leeren soll. Seit ich den DocumentFilter eingebunden habe, klappt das aber nicht mehr. Die Textfelder werden nicht zurückgesetzt (geleert).
Vllt. in deiner if-Abfrage noch ein [c] || str.isEmpty()[/c] einbauen?
 
Einfach vorne mit rein setzen? -> "[ A-Za-zßé-]+"
Ah OK, hab's immer hinten mit dran gesetzt, was mir dann ne Exception gemeldet hatte:
Java:
java.util.regex.PatternSyntaxException: Illegal character range near index 10
[A-Za-zßé- ]+

Obs da schon ein vernünftiges Pattern gibt? Von Haus aus sicherlich nicht, im Internet generell? Bestimmt ist irgendwo etwas zu finden. Vllt. wäre es leichter einen bestimmten ASCII Bereich zu filtern, anstelle einzelne Zeichen aufzuzählen ?!
Wie kann ich denn einen bestimmten ASCII-Bereich dem Pattern hinzufügen? Soweit ich das gerade überblicke, sind ja auch nicht alle möglichen Zeichen fortlaufend in der ASCII-Tabelle, müssten dann also auch zum Teil einzeln aufgezählt werden.

Vllt. in deiner if-Abfrage noch ein [c] || str.isEmpty()[/c] einbauen?
Hey cool, das klappt nun auch...

Danke für die Hilfe.
 
Hmm, wenn ich das richtig sehe, müssten mit den ASCII-Zeichen 128-154, 160-165 und 225 so ziemlich alle möglichen Sonderzeichen abgedeckt sein, welche in Namen vorkommen könnten.
 
Hatte ich im Internet in ASCII-Tabellen gefunden. Uiuiuiui, muss mich wohl erst mal genauer mit der Materie ASCII beschäftigen...
 
OK, also laut der erweiterten ASCII-Tabelle müssten die Sonderzeichen alle zwischen 192 und 255 liegen. Nur wie kriege ich das jetzt in mein Pattern rein?
 
Also da wären dann aber auch z.B. das Durchmesser-Zeichen erlaubt? :autsch:
ASCII-Tabelle

Aber generell geht`s z.B. (bezogen auf deinen Bereich) so:
192 = C0 Hexa
255 = FF Hexa
= Pattern --> [\\xC0-\\xFF]
 
Dann würde mein Pattern letztlich also so aussehen:

[ A-Za-z-\\xC0-\\xFF]+

So scheint es jedenfalls zu funktionieren. Ich kann nun alle Buchstaben, auch Umlaute und Sonderzeichen eingeben, und auch Leerzeichen und den Bindestrich. Oder ist da noch etwas falsch oder verbesserungswürdig?
 

Zurück
Oben