JTextField: Dokumentarten

Status
Nicht offen für weitere Antworten.

thE_29

Top Contributor
Da es schon oft vorgekommen ist, das jemand ein Textfield umändern, sodass es entweder nur ein Datumsfeld (ja, es gibt schon ein vordefiniertes Datum Textfield, aber egal ;)) oder ein IntegerFeld haben will, poste ich mal 2 Bsp, wie man sich ein Document zusammenbasteln kann!

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

Java:
//zuerst wie setze ich es
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 ;)


Nun hier noch ein DoubleDocument (damit auch Kommazahlen funktionieren!)
Java:
//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 nich 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);
    }
  }

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

Java:
//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) {}
  }

  /**
   * 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 euch mit dem Integerdocument rum, wenn ihr das Datedocument nicht versteht ;)

Aber so kann man vieles machen, hab noch ein IPFeld und ein MoneyFeld, usw...

Ist eigentlich immer das gleiche!
 

thE_29

Top Contributor
So, habe aufgrund eines Users ein neues Document gemacht und zwar ein NegativeDoubleDocument(JTextField)

Achja, das DefaultKommazeichen ist ein . und er wandelt die , in einen Punkt um (auch während der Eingabe)

Zuweisen geht es wie das normale DoubleDocument(JTextField) also so


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


Hier der Code der Klasse! (wenn ihr NegativeLongDocument braucht einfach sagen, habe ich irgendwann mal entworfen bin aber zu faul zum Suchen ;))


Java:
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);
          }
    }



Bei Fehlern bitte berichten ;)
 

André Uhres

Top Contributor
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:
Java:
int MAX = 8;
JTextField textfield = new JTextField(MAX);
((AbstractDocument) textfield.getDocument()).setDocumentFilter(new DocumentSizeFilter(MAX, "[A-Za-z]+"));
Java:
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();
        }
    }
}
 
Status
Nicht offen für weitere Antworten.

Oben