JTextField begrenzen und nur Zahlen.

Kai008

Erfahrenes Mitglied
Ich will in meinen JTextField nur max. 6 Zeichen/Zahlen zulassen, alle anderen Zeichen sollen keine Änderung vornehmen.

Nur irgendwie kriege ich es einfach nicht hin.
Zum einen sind jetzt 7 Zeichen möglich, obwohl ich ja beim 7. Zeichen wieder auf den alten Wert (der ja 6 enthält) zurücksetzen will.
Und irgendwie kann ich noch immer noch einen Buchstaben/Zeichen eintippen, obwohl er in dem Fall ja sofort wieder auf einen (zeichen-)leeren String zurücksetzen sollte.
Kann mir wer bitte sagen, woran diese Fehler liegen?

Ach ja, ich weiß dass es womöglich mit den Integer-Werten der Chars einfacher wäre, aber dafür müsste man einerseits die ASCII-Tabelle auswendig kennen (gut, wo Buchstaben/Zahlen/Symbole/Steuerzeichen anfangen/aufhören lernt man zwar von alleine auswendig), aber so kann man z. B. auch einen Filter bauen, was wenn man z. B. nur bestimmte Zeichen reinlassen will mit Ints echt schwer/verwirrend wäre.


Java:
package login;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JTextField;

public class ClientNumberField extends JTextField implements KeyListener
{
	private static final long serialVersionUID = 1L;
	private static final char[] NUMERIC_CHARS = {
		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
	};
	private static final char[] MIXALPHA_SYMBOLIC_CHARS = {
		'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
		'V', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
		'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '^', '°', '!', '"', '§', '$', '%', '&', '/', '(', ')', '=',
		'?', '`', '´', '²', '³', '{', '[', ']', '}', '\\', '*', '+', '~', '\'', '#', ';', ',', ':', '.', '_', '-', '<',
		'>', '|' 
	};
	
	private static String textCache;
	
	public ClientNumberField()
	{
		super("");
		super.addKeyListener(this);
		textCache = this.getText();
	}
	
	public void keyPressed(KeyEvent arg0)
	{
		if(arg0.getKeyCode() == KeyEvent.VK_ENTER)
		{
			if(textfieldTextIsNumeric(this.getText()))
				Loginform.getComponent(Loginform.COMPONENT_CLIENT_YEAR_FIELD).requestFocus();
			else
				this.select(0, this.getText().length());
		}
	}
	public void keyReleased(KeyEvent arg0){}
	public void keyTyped(KeyEvent arg0)
	{
		if(keycharIsNumeric(arg0.getKeyChar()))
		{
			if(this.getText().length() > 6)
				this.setText(textCache);
			else
				textCache = this.getText();
			System.out.println("Num");
		}
		else if(keycharIsMixalphaSymbolic(arg0.getKeyChar()))
		{
			this.setText(textCache);
			System.out.println("Al/Sym");
		}
	}
	
	private boolean textfieldTextIsNumeric(String text)
	{
		boolean result = true;
		
		for(byte b = 0; b < text.length() && result; b++)
		{
			char c = text.charAt(b);
			
			if((c != NUMERIC_CHARS[0]) && (c != NUMERIC_CHARS[1]) && (c != NUMERIC_CHARS[2]) &&
					(c != NUMERIC_CHARS[3]) && (c != NUMERIC_CHARS[4]) && (c != NUMERIC_CHARS[5]) &&
					(c != NUMERIC_CHARS[6]) && (c != NUMERIC_CHARS[7]) && (c != NUMERIC_CHARS[8]) &&
					(c != NUMERIC_CHARS[9]))
				result = false;
		}
		return(result);
	}
	private boolean keycharIsNumeric(char keychar)
	{
		boolean result = false;
		
		for(int b = 0; (b < NUMERIC_CHARS.length) && (!result); b++)
			if(keychar == NUMERIC_CHARS[b])
				result = true;
		return(result);
	}
	private boolean keycharIsMixalphaSymbolic(char keychar)
	{
		boolean result = false;
		
		for(int b = 0; (b < MIXALPHA_SYMBOLIC_CHARS.length) && (!result); b++)
			if(keychar == MIXALPHA_SYMBOLIC_CHARS[b])
				result = true;
		return(result);
	}
}
 
Ich hatte mal ein ähnliches Problem. Ich brauchte für eine GUI ein Textfeld, das den Port für die Netzwerkverbindung aufnehmen sollte. Ich habe auch einiges ausprobiert und bin irgendwann im Internet auf etwas gestoßen, das mir sehr geholfen hat. Anstatt nem KeyListener benutzt man ein Document-Objekt, das die Eingabe überwacht.

Hier mal mein Code für das Textfeld:
Java:
private JTextField getPortTextField() {
	if(portTextField == null) {
		portTextField = new JTextField();
		
		/*
		 * Das Textfeld soll nur Zahlen zulassen und als Maximum soll
		 * maximal eine fünfstellige Zahl im Textfeld stehen.
		 */
		portTextField.setDocument(new PlainDocument() {
			private static final long serialVersionUID = 1L;

			@Override
			public void insertString(int off, String str, AttributeSet as) throws BadLocationException {
				// Prüfen, ob bereits 5 Zeichen drin stehen
				if(getLength() >= 5) return;

				// Prüfen, ob die einzufügenden Zeichen Zahlen sind
				for(int i = 0; i < str.length(); i++) {
					if(!Character.isDigit(str.charAt(i))) return;
				}

				// Zahl(en) einfügen
				super.insertString(off, str, as);
			}
		});
	}

	return portTextField;
}

Wie gesagt, interessant ist der Teil, wo ein Document-Objekt gesetzt wird. Die Methode insertString wird überlagert, in ihr der einzufügende Kram getestet und wenn alles passt, dann wirds eingefügt. Musst du dann natürlich an deinen Code anpassen.

Diese Variante hat auch noch den Vorteil, dass nicht nur die Tastenschläge überwacht werden. Dabei könnte man ja trotzdem ungültige Zeichen einschleusen, z.B. via Copy-Paste. Hierbei geht das nicht.
 
Zuletzt bearbeitet:
Danke.
Die Zeichenbegrenzung lässt sich dadurch zwar immer noch umgehen, aber da kommt am Ende einfach ne zusätzliche Prüfung hin.
Funktioniert ansonst wunderbar. =)
 
Zurück