Newsgroup: it.comp.java
Titolo: Ancora sui TextField

Visto che a qualcuno interessava (e sta interessando anche a me.. :) ecco
cosa ho buttato giu' per realizzare un TextField con un vincolo sul numero
massimo dei caratteri inseribili. Ovviamente e' una sottoclasse del
TextField di AWT, il "trucco" sta nel gestire gli eventi di modifica del
testo in modo tale da fare sparire il primo carattere che eccede la
capacita' massima, senza dimenticarsi di ripristinare la posizione del
cursore. Ah, sono un principiante, quindi sparate pure..
Richiede Java 1.1; ho provato anche a fare una conversione in maiuscolo "al
volo" (in pratica vorrei che i caratteri comparissero in maiuscolo al
momento della battitura), ma ho cozzato contro del problemi di eventi che
entrano in loop.. se qualcuno sa come fare, dica pure, possibilmente
rimanendo nell'ambito dell'AWT (vorrei evitare Swing per ora).
Seguono la classe FLTextField e il programmino di esempio.
// --- Fixed Length Text Field
import java.awt.*;
import java.awt.event.*;
public class FLTextField extends TextField {
 private int maxChars;
 FLTextField(int maxChars) {
  super(maxChars);
  this.maxChars=maxChars;
  addTextListener(new T());
 }
 class T implements TextListener {
  public void textValueChanged(TextEvent e) {
   String s=getText();
   int c=getCaretPosition();
   if (s.length()>maxChars) {
    //--- elimina il nuovo carattere
    setText(s.substring(0, c-1)+s.substring(c)); 
    //--- ripristina la posizione del cursore
    setCaretPosition(c-1);
   }
  }
 }
}
// --- Test per Fixed Length Text Field 
import java.awt.*;
public class TestFLTextField extends Frame {
 TestFLTextField() {
  super("Test FLTextField");
  setLayout(new FlowLayout(FlowLayout.LEFT));
  add(new Label("Max 10 caratteri:"));
  FLTextField t1=new FLTextField(10);
  add(t1);  
  add(new Label(" 1 carattere solo:"));
  FLTextField t2=new FLTextField(1);
  add(t2);  
 }
 public static void main(String[] args) {
  TestFLTextField app=new TestFLTextField();    
  app.pack();
  app.setVisible(true);
 }
 
}

 massimo dei caratteri inseribili. Ovviamente e' una sottoclasse del
Piero, sono riuscito a ritrovare alcune classi che avevo realizzato
quando muovevo i primissimi passi in Java. Sono dei beans, quindi puoi
sbatterteli nella palette del tuo IDE se vuoi (io le avevo infilate
sotto JBuilder, se proprio ci tieni ti posso far avere anche le icone :)
Questa controlla la lunghezza massima di una stringa, nonchč puň forzare
a maiuscolo/minuscolo:
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;
import com.sun.java.swing.event.*;
public class JControlCaseTextField extends JTextField implements
KeyListener {
  private boolean forceLower;
  private boolean forceUpper;
  private int maxLength;
  public JControlCaseTextField() {
    maxLength = -1;
    this.addKeyListener(this);
  }
  public boolean isForceLower() {
    return forceLower;
  }
  public void setForceLower(boolean force) {
    forceLower = force;
    if (force == true)
      forceUpper = false;
  }
  public boolean isForceUpper() {
    return forceUpper;
  }
  public void setForceUpper(boolean force) {
    forceUpper = force;
    if (force == true)
      forceLower = false;
  }
  public void setMaxLength(int newMaxLength) {
    maxLength = newMaxLength;
  }
  public int getMaxLength() {
    return maxLength;
  }
  public void keyReleased(KeyEvent e) {}
  public void keyPressed(KeyEvent e) {}
  public void keyTyped(KeyEvent e) {
    String ts = getText();
    int cp = getCaretPosition();
    char c = e.getKeyChar();
    if (c == KeyEvent.VK_BACK_SPACE) {
      if( ts.length() > 0) {
        String head = ts.substring(0, cp);
        String tail = ts.substring(cp);
        setText(head + tail);
      }
    }
    else if (c == KeyEvent.VK_ENTER) {
    }
    else if (maxLength == -1 || ts.length() < maxLength) {
      if (forceUpper)
        c = Character.toUpperCase(c);
      else
      if (forceLower)
        c = Character.toLowerCase(c);
      String head = ts.substring(0, cp);
      String tail = ts.substring(cp);
      setText(head + c + tail);
      cp++;
    }
    setCaretPosition(cp);
    e.consume();
  }
}
Quest'altra costringe a immettere solo cifre:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.text.*;
public class JNumericTextField extends JControlCaseTextField implements
KeyListener{
  private boolean allowDecimal;
  private static char decSep;
  static {
    DecimalFormatSymbols symbols = new
DecimalFormatSymbols(Locale.getDefault());
    decSep = symbols.getDecimalSeparator();
  }
  public JNumericTextField() {
  }
  public void setAllowDecimal(boolean allow) {
    allowDecimal = allow;
  }
  public boolean isAllowDecimal() {
    return allowDecimal;
  }
  public void keyTyped(KeyEvent e) {
    char c = e.getKeyChar();
    if (c >= '0' && c <= '9' || (c == decSep && allowDecimal == true &&
getText().indexOf(decSep) == -1))
      super.keyTyped(e);
    else
      e.consume();
  }
  public double toDouble() {
    String s = getText();
    if (s.equals(""))
      return (double)0.0;
    int i = s.indexOf(decSep);
    if (i != -1)
      s = s.substring(0, i) + "." + s.substring(i+1);
    return Double.valueOf(s).doubleValue();
  }
}
Ovviamente non sono perfette. C'č il modo di infilare 50 caratteri con
un limite di 10. Vediamo se lo trovi? La soluzione, che avevo trovato ma
mai implementato per mancanza di tempo, stava nel controllare il
documento attaccato al textfield e non il textfield stesso.
Ciao,
	Stefano