JTextField - Dokumentarten

Aus Byte-Welt Wiki
Wechseln zu: Navigation, Suche

IntegerDocument

Als erstes das IntegerDocument (es lässt euch nur Zahlen eingeben!)

//zuerst wie es gesetzt wird
JTextField tmp = new JTextField();
tmp.setDocument(new IntegerDocument()); 
 
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*; 
 
public class IntegerDocument extends PlainDocument
{
   public void insertString(int offset, String s, AttributeSet attributeSet) throws BadLocationException
    {
      try{
             Integer.parseInt(s);
         }
         catch(Exception ex)   //only allow integer values
         {
            Toolkit.getDefaultToolkit().beep(); //macht ein DßT
            //System.out.println("Keine Zahl!");
            return ;
         }
      super.insertString(offset,s, attributeSet);
    }
}

Dies ist ganz simple und ich glaube für jeden zu verstehen


DoubleDocument

Nun hier noch ein DoubleDocument (damit auch Kommazahlen funktionieren!)

//Aufruf
JTextField text = new JTextField(new DoubleDocument(text));
text.setText("12.10");
 
 
//andere Klasse
   public class DoubleDocument extends PlainDocument
  {
    private boolean bDot = false;
    private JTextField jtTxt = null;
 
    public DoubleDocument(JTextField txt)
    {
      this.jtTxt = txt;
    }
 
    public void insertString(int offset, String s, AttributeSet attributeSet) throws BadLocationException
    {
      bDot = jtTxt.getText().toString().indexOf(".") == -1 ? false : true;
      try{
        if(s.indexOf(".") != -1 && s.length() > 1) //überprüfe einen ganzen String und nicht 1 Zeichen
          bDot = true;
        System.out.println(">>>> 3 >> " + bDot);
        if(!s.equals(".")) //wenn es sich um keinen KommaPunkt handelt
          Double.parseDouble(s);
        else if(bDot)
          throw new Exception();
        else
          bDot = true;
      }
      catch(Exception ex)   //only allow integer values
      {
        Toolkit.getDefaultToolkit().beep(); //macht einen Ton
        //System.out.println("Keine Zahl!");
        return ;
      }
      super.insertString(offset,s, attributeSet);
    }
  }


DateDocument

Nun ein DateDocument, was schon bißchen schwieriger zu verstehen ist, weil man gewisse Abfragen hat...

//zuerst, wie setze ich es
JTextField tmp = new JTextField();
tmp.setDocument(new DateDocument(tmp));
 
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import java.awt.event.KeyEvent;
import java.text.*;
import java.util.Date;
import java.util.GregorianCalendar;
 
public class DateDocument extends PlainDocument
{
  public String initString = "yyyy MM dd";
  private int ivorher = 0;
 
  Date datum = new Date();
  private String str;
  private static int sep1 = 4, sep2 = 7;
  private JTextComponent textComponent;
  private int newOffset;
 
  /**
   * Überprüft eingegebenes Zeichen auf seine Gültigkeit->
   * Buchstaben oder sonstige Zeichen sind nicht zulässig
   * @param tc JTextComponent
   */
  public DateDocument(JTextComponent tc)
  {
    textComponent = tc;
    try{
         insertString(0,initString,null);
       }
       catch(Exception ex) {
          ex.printStackTrace();
       }
  }
 
 
  /**
   * Versucht das eingegebene Zeichen auf einen Integer zu parsen. Zusätzlich wird
   * überprüft, wo sich der Cursor befindet (womöglich vor einem Trennzeichen, das
   * übersprungen werden soll). Tage und Monate werden bereits während der Eingabe
   * auf ihre Gültigkeit (z.B. Tag: 32 -> falsch, Monat: 13 -> falsch) überprüft.
   * @param offset  Position im String (ist zu vergleichem mit dem Initialisierungsstring)
   * @param s       Zeichen, das überprüft wird
   * @param attributeSet  AttributeSet wird nur an die Vaterklasse weitergeleitet
   * @throws BadLocationException  wird geworfen, wenn das Zeichen nicht geparst werden kann
   */
  public void insertString(int offset, String s, AttributeSet attributeSet) throws BadLocationException
  {
     if(s.equals(initString))
        super.insertString(offset,s,attributeSet);
     else
     {
         try
         {
            //DateFormat format = DateFormat.getDateInstance();
            SimpleDateFormat format = new SimpleDateFormat(initString);
            format.setLenient(false);       //ßberprüfung auf korrektes Datum
            Date dDatum = format.parse(s);
            super.remove(0,textComponent.getText().length());
            super.insertString(offset,s,attributeSet);
         }
         catch(Exception ex)
         {
             try
             {
               Integer.parseInt(s);
 
               newOffset = offset;
               if(atSeparator(offset))
               {
                 newOffset++;
                 textComponent.setCaretPosition(newOffset);
               }
               if(!dateIsOk(//textComponent.getText(0,newOffset)+
               s,newOffset))
               {
                  Toolkit.getDefaultToolkit().beep();
                  return;
               }
 
               super.remove(newOffset,1);
               super.insertString(newOffset,s,attributeSet);
             }
 
             catch(Exception ex2)
             {
               return; //only allow integer values
             }
         }
     }
  }
 
  /**
   *
   * @param offset  Position im String (ist zu vergleichen mit dem Inititialisierungsstring)
   * @param length  Länge des Strings
   * @throws BadLocationException  Wenn eine Position nicht verwendet bzw. ermittelt werden kann
   */
  public void remove(int offset, int length) throws BadLocationException
  {
     if(atSeparator(offset))
       textComponent.setCaretPosition(offset-1);
     else textComponent.setCaretPosition(offset);
  }
 
  /**
   * @param offset Position im String (ist zu vergleichen mit dem Initialisierungsstring)
   * @return boolean, true für Separater ist am offset, false für kein Separator
   */
  public boolean atSeparator(int offset)
  {
     return offset == sep1 || offset == sep2; //false
  }
 
  /**
   * Überprüft das eingegebene Datum auf seine Richtigkeit
   * @param txtDate  Zeichen (als String), das überprüft wird
   * @param off      Offset des Zeichens
   * @return         true für Datum ist ok, false für nicht möglich
   */
 private boolean dateIsOk(String txtDate,int off)
 {
   boolean ret = false;
   int curScan = 0;
   String cur = "";
   int len = 0;
   len = off+1;
   String svorher ="";
   String s ="";
   if(len < 1)
     curScan = 0;
   else curScan = len -1;
 
   try{
       s = initString.substring(len-1, len);
      if(curScan != 0)
         svorher = initString.substring(curScan-1, len-1);
      else
         svorher = "F";
      int izahl = Integer.parseInt(txtDate);
 
      if (s.compareTo("M")== 0)
      {
        if (svorher.compareTo("M") != 0)
        {
          if (izahl > 1)
            ret = false;
          else
            ret = true;
          ivorher = izahl;
        }
        else {
            if (ivorher == 1 && izahl > 2)
              ret = false;
            else if(ivorher == 0 && izahl == 0)
              ret = false;
            else
              ret = true;
            }
      }
      if (s.compareTo("d")==0 || s.compareTo("D")==0)
      {
        if (svorher.compareTo("d") !=0 && svorher.compareTo("D") !=0 )
        {
          if (izahl > 3)
            ret = false;
          else
            ret = true;
        ivorher = izahl;
        }
        else {
          if (ivorher == 3 && izahl > 1)
            ret = false;
          else if(ivorher == 0 && izahl == 0)
            ret = false;
          else
            ret = true;
 
        }
      }
      if(s.compareTo("y") == 0 || s.compareTo("Y")==0)
      {
        ret = true;
      }
 
    }catch(Exception ex){
      //ex.printStackTrace(System.out);   //soll nicht geworfen werden, weil Jahre noch nicht überprüft werden
                                //bringt Error, wenn an letzter Stelle noch Ziffer eingegeben wird.
    }
    finally{
      return ret;
    }
  }
}

Am besten ist, ihr spielt erst mal mit dem Integerdocument rum, wenn ihr das Datedocument noch nicht versteht.


NegativeDoubleDocument

Das DefaultKommazeichen ist ein . und er wandelt die , in einen Punkt um (auch während der Eingabe). Zuweisen geht wie beim "normalen" DoubleDocument -> DoubleDocument(JTextField) also.

JTextField myField = new JTextField();
myField.setDocument(new NegativeDoubleDocument());
myField.setText("110000,100");
myField.setText("-200,20"); //das geht auch, alle "," werden durch "." ersetzt

Nun noch der Code von NegativeDoubleDocument.

import javax.swing.text.PlainDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.JTextField;
import java.awt.Toolkit;
 
public class NegativeDoubleDocument extends PlainDocument
{
  private boolean bDot = false;
       /***************************************************************************
       * Funktion erlaubt ein minus oder + (nicht sichtbar) in den Zahlen
       * @param offset int
       * @param s string
       * @param attributeSet att
       * @throws BadLocationException
       **************************************************************************/
      public void insertString(int offset, String s, AttributeSet attributeSet) throws
          BadLocationException
      {
        try
            {
              if(s.equals(",")) //ersetzt den , durch einen Punkt
                s = ".";
              bDot = getText(0,getLength()).indexOf(".") == -1 ? false : true; //merkt sich ob ein Punkt oder nicht
              if (s.length() > 1)
              {
                //wenn der String größer als 1 ist, ist es eine ganze IP und somit eine Schleife
                for(int x = 0; x != s.length(); x++)
                  insertString(x,s.substring(x,x+1).replaceFirst(",","."),null); //ersetzt , durch Punkt
                //mach gar nix, weil die for schleife alles macht!
                  return;
              }
              else if(s.equals("-"))
              {
                String strTmp = getText(0,getLength()); //holt sich den Text
                System.out.println(strTmp);
                if(strTmp.indexOf("-")!=-1) //schaut nach ob ein minus vorhanden ist
                  strTmp = strTmp.replaceAll("-",""); //wenn ja weg
                else
                  strTmp = "-" + strTmp;
                replace(0,getLength(),null,attributeSet);
                super.insertString(0,strTmp,attributeSet);
                return;
              }
              else if(s.equals("+")) //bei einem + einfach ein weiteres - hinzufügen
              {
                if(getText(0,getLength()).indexOf("-")!=-1)
                  insertString(0,"-",attributeSet); //ruft sich selbst mit - auf und dann kommt obige ßberprüfung
                return;
              }
              //OPTIONAL!! STATT DEM ± kann man jedes Zeichen nehmen oder komplett weglassen
              //wenn man irgendwelche Zeichen zB noch haben will <!--- OPTIONAL ---!>
              else if(s.equals("±"))
              {
                String strTmp = getText(0,offset);
                if(strTmp.indexOf("±") != -1)
                  strTmp = strTmp.replaceAll("±","");
                else
                  strTmp = "±" + strTmp;
                replace(0,getLength(),null,attributeSet);
                super.insertString(0,strTmp,attributeSet);
                return; //damit aufgehört wird
              }
              //ENDE OPTIONAL!!
             //wenn das aktuelle Zeichen kein punkt ist oder wenn es ein Punkt ist und schon ein Punkt eingegegeben ist
              else if(!s.equals(".") || bDot)  // ==   if(!(s.equals(".") && !bDot))
                Double.parseDouble(s);
            }
            catch(Exception ex)
            {
              Toolkit.getDefaultToolkit().beep();
              return;
            }
            super.insertString(offset,s, attributeSet);
          }
    }
}


DocumentFilter

Zitat: "Ich will ein JTextField so verändern, dass man maximal 8 Zeichen eingeben kann und nur Groß- und kleinbuchstaben zugelassen sind (also keine Sonderzeichen, Punkte, usw.)."

Wir könnten einen DocumentFilter setzen, etwa so:

int MAX = 8;
JTextField textfield = new JTextField(MAX);
((AbstractDocument) textfield.getDocument()).setDocumentFilter(new DocumentSizeFilter(MAX, "[A-Za-z]+"));
import javax.swing.text.*;
import java.awt.*;
import javax.swing.*;
 
public class DocumentSizeFilter extends DocumentFilter {
    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);
        } else {
            Toolkit.getDefaultToolkit().beep();
        }
    }
}

--thE_29 (26.08.2004)