Esse tópico surgiu depois de tentar entender o artigo Controlando um JTextField e outro, baseado nesse primeiro, chamado JTextField´s formatado em tempo execução.
Basicamente queria extender PlainDocument e utilizar JTextField para a entrada dos dados; e não utilizar MaskFormatter e JFormattedTextField.
Imagino chegar numa solução (será que uma única classe resolve?) para controlar textos e valores monetários - a princípio.
Vou postar aqui inicialmente duas classes:
PARA CONTROLAR TEXTOS (peguei do site javadesk e modifiquei ela):
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
public class FormataTexto extends PlainDocument {
private int iMaxLength = 0;
private char tipo;
Pattern texto;
public FormataTexto(int maxlen, char tp) {
super();
iMaxLength = maxlen;
tipo = tp;
}
public String formatar (String entrada, Integer valor){
// 1 - somente letras e números
// 2 - somente numeros
// 3 - somente letras
if (valor == 1){
texto = Pattern.compile("[0-9a-z]",Pattern.CASE_INSENSITIVE);
} else if (valor == 2){
texto = Pattern.compile("[0-9]",Pattern.CASE_INSENSITIVE);
} else if (valor == 3){
texto = Pattern.compile("[a-z]",Pattern.CASE_INSENSITIVE);
}
Matcher encaixe = texto.matcher(entrada);
StringBuffer saida = new StringBuffer();
while(encaixe.find())
saida.append(encaixe.group());
return saida.toString();
}
@Override
public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException {
if ( str == null ) return;
boolean ok = true;
if ( iMaxLength <= 0 ) {// aceitara qualquer no. de caracteres
super.insertString( offset, str, attr );
return;
}
// A = TUDO
// B - SOMENTE LETRAS E NÚMEROS EM MAIÚSCULO
// C - somente letras e números em minúsculo
// D - SOMENTE NÚMEROS
// E - SOMENTE LETRAS MAIÚSCULO
// F - SOMENTE LETRAS minúsculo
switch(tipo) {
case 'B': str = formatar(str.toUpperCase(), 1); break;
case 'C': str = formatar(str.toLowerCase(), 1); break;
case 'D': str = formatar(str, 2); break;
case 'E': str = formatar(str.toUpperCase(), 3); break;
case 'F': str = formatar(str.toLowerCase(), 3); break;
}
int ilen = (getLength() + str.length());
if ( ilen <= iMaxLength ) // se o comprimento final for menor...
super.insertString( offset, str, attr ); // aceita str
else {
if ( getLength() == iMaxLength ) return; // nada a fazer
String newStr = str.substring(0, (iMaxLength - getLength()));
super.insertString( offset, newStr, attr );
}
}
}
uso ela dessa maneira:
JTextFiledNome = new JTextField(10); //tamanho do jtextfield
JTextFiledNome .setDocument(new FormataTexto(20, 'E')); //permite no máximo 20 caracteres, somente letras maiusculas
PARA CONTROLAR VALORES MONETÁRIOS (peguei esse código aqui no GUJ, parece que foi de um post do Mark_Ameba:
[code]
import javax.swing.text.*;
public class MonetarioDocument extends PlainDocument {
public static final int NUMERO_DIGITOS_MAXIMO = 12;
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
String texto = getText(0, getLength());
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (!Character.isDigit©) {
return;
}
}
if(texto.length() < this.NUMERO_DIGITOS_MAXIMO){
super.remove(0, getLength());
texto = texto.replace(".", “”).replace(",", “”);
StringBuffer s = new StringBuffer(texto + str);
if (s.length() > 0 && s.charAt(0) == ‘0’) {
s.deleteCharAt(0);
}
if(s.length() < 3) {
if (s.length() < 1) {
s.insert(0,“000”);
}else if (s.length() < 2) {
s.insert(0,“00”);
}else{
s.insert(0,“0”);
}
}
s.insert(s.length()-2, “,”);
if(s.length() > 6) {
s.insert(s.length()-6, “.”);
}
if(s.length() > 10) {
s.insert(s.length()-10, “.”);
}
super.insertString(0, s.toString(), a);
}
}
public void remove(int offset, int length) throws BadLocationException {
super.remove(offset, length);
String texto = getText(0, getLength());
texto = texto.replace(",", “”);
texto = texto.replace(".", “”);
super.remove(0, getLength());
insertString(0, texto, null);
}
} [/code]
da mesma forma, uso ela assim:
JTextFieldDinheiro = new JTextField(8);
JTextFieldDinheiro .setDocument(new MonetarioDocument());
Perguntas:
1 - É possível otimizar e unir esses códigos (principalmente a primeira classe), deixando somente numa classe melhorada? alguma dica?
2 - É possível, nesse raciocínio, fazer com que a tecla ENTER se comporte como TAB? (tenho que ver o método Character.isISOControl());
3 - É possível, quando o JTextField receber o foco, selecionar todo o seu conteúdo?
(já fiz a pergunta 2 e 3, separadamente, penso em chegar num modelo onde não precise fazer isso componente por componente)
espero ajuda!