# JTextField mit Zeichenbeschränkung



## Guest (4. Jul 2008)

Gibts irgendwo schon ein Textfeld mit einer Zeichenbeschränkung für
-min/max Länge (bei Unterschreitung der min-Länge wird z.B. der Hintergrund rot gefärbt, max Länge lässt sich nicht überschreiten)
-Inhalt (z.B. per Regex beschränken sodass man z.B. nur ein Datum im Format dd.MM.yyyy eingeben kann, falsches Format => roter Hintergrund)


----------



## masta // thomas (4. Jul 2008)

Schau dir mal das JGoodies Validation Framework an, ich glaube, das ist was für dich.


----------



## SlaterB (4. Jul 2008)

das gute alte Swing ist da aber auch nicht ganz ohne Möglichkeiten,

einfach mal ein Lehrbuch/ Tutorial aufschlagen?..
http://java.sun.com/docs/books/tutorial/uiswing/components/textfield.html
->
http://java.sun.com/docs/books/tutorial/uiswing/components/formattedtextfield.html


----------



## Niki (4. Jul 2008)

Es gibt das JFormattedTextField. Ich weiß aber nicht ob das für deine Ansprüche genügt. Ansonsten bleibt dir nichts anderes übrig als dein eigenes Document zu schreiben (von PlainDocument ableiten und die insertString-Methode überschreiben). Das würde dann so aussehen:

```
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

public class CustomDocument extends PlainDocument {

	public CustomDocument(int max, String regex) {
		setMax(max);
		setRegex(regex);
	}

	private int max = 0;
	private String regex = null;

	public int getMax() {
		return max;
	}

	public void setMax(int max) {
		this.max = max;
	}

	public String getRegex() {
		return regex;
	}

	public void setRegex(String regex) {
		this.regex = regex;
	}

	@Override
	public void insertString(int offs, String str, AttributeSet a)
			throws BadLocationException {

		if (str.length() + getLength() > max)
			return;

		StringBuffer sb = new StringBuffer(getText(0, getLength()));
		sb.insert(offs, str);

		//nur wenn der String der regex entspricht soll der String eingefügt werden, ansonsten wird nichts gemacht
		if (sb.toString().matches(regex))
			super.insertString(offs, str, a);
	}
	
	public boolean isValid(){
		try {
			return getText(0, getLength()).matches(regex);
		} catch (BadLocationException e) {
			return false;
		}
	}
}
```

Und das TextField dazu:

```
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.WindowConstants;

public class CustomTextField extends JTextField {

	private int min = 0;

	public CustomTextField(int min, int max, String regex) {
		this.min = min;
		setDocument(new CustomDocument(max, regex));

		addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(FocusEvent e) {
				_validate();
			}
		});
		
		addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				_validate();
				
			}
		});
	}
	
	private void _validate(){
		if(isContentValid()){
			setBackground(Color.WHITE);
			setForeground(Color.BLACK);
		} else {
			setBackground(Color.RED);
			setForeground(Color.WHITE);
		}
	}

	public boolean isContentValid() {
		int length = getText().length();
		if (length < min) {			
			return false;
		}		
		return true;
	}
	
	public static void main(String[] args) {
		JFrame jf = new JFrame("Test CustomDocument");
		CustomTextField tf = new CustomTextField(5, 10, "[\\d]*");
		jf.add(tf);
		jf.pack();
		jf.setLocationRelativeTo(null);
		jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		jf.setVisible(true);
	}
}
```

Das obige Beispiel lässt nur Zahlen mit mindestens 5 und maximal 10 Stellen zu.


----------



## Eminent (4. Jul 2008)

Also wir machen das hier bei uns immer so wie Niki aufgezeigt hat.

Es ist zwar für Kleinigkeiten vielleicht etwas übertrieben aber dafür sind die Möglichkeiten auch sehr umfangreich. So ist es hier auch wesentlich leichter möglich eingefügte Textteile (z. B. über Strg+V) einfach mit einzubauen und in die Prüfungen und mögliche Formatierungen mit einzuarbeiten.


----------



## Marco13 (4. Jul 2008)

Jup, das CustomTextField könnte auch ein DocumentListener sein - dann wird bei JEDER Veränderung (und nicht nur bei focusLost oder ENTER) die Farbe passend gesetzt.

Sowas wie

```
private void _validate(){
      if(isContentValid())
      {
...
      } else {
         setBackground(Color.RED); //----------- !!! doppelt
         setForeground(Color.WHITE);
      }
   }

   public boolean isContentValid() {
      int length = getText().length();
      if (length < min) {
         setBackground(Color.RED); //----------- !!! doppelt
         return false;
      }
```
könnte/sollte man vielleicht noch verbessern, aber... das nur nebenbei....


----------



## Niki (4. Jul 2008)

Ups, das sollte natürlich noch rausgelöscht werden


----------



## André Uhres (4. Jul 2008)

Zum Einschränken der Anzahl von Zeichen, die der Benutzer eingeben darf, 
können wir unser eigenes Document setzen, wie auch schon vorgeschlagen wurde:


```
dateField.setDocument(new PlainDocument() {
    public void insertString(final int offs, final String str, 
            final AttributeSet a) throws BadLocationException {
        if(getLength() + str.length() > 10){
            Toolkit.getDefaultToolkit().beep();
        }else{
            super.insertString(offs, str, a);
        }
    }
});
```



Ferner können wir die Methode JComponent#setInputVerifier(..) benutzen, 
um unseren eigenen InputVerifier an das JTextField zu hängen.
Die Klasse InputVerifier stellt sicher, daß der Text, den der Benutzer eigegeben hat, 
gültig ist, bevor dem Benutzer erlaubt wird, das Textfeld zu verlassen. Hier ein Beispiel:


```
class DateVerifier extends InputVerifier {
    private String patternE;
    private SimpleDateFormat formatterE;
    private Border border1;
    private Border border2;
    public DateVerifier() {
        patternE = "dd/MM/yyyy";
        formatterE = new SimpleDateFormat(patternE);
        formatterE.setLenient(false);
        border2 = new LineBorder(Color.red);
    }
    public boolean verify(final JComponent input) {
        JTextField tf = (JTextField) input;
        if(border1 == null){
            border1 = tf.getBorder();
        }
        try {
            Date date = formatterE.parse(tf.getText());
            tf.setBorder(border1);
            System.out.println(date);
            return true;
        } catch (ParseException e) {
            tf.setBorder(border2);
            return false;
        }
    }
}
```


----------

