Formatando

10 respostas
D

Galera é o seguinte, eu tenho jtextfield e quero formatá-lo para receber uma data (exemplo: 01/05/2010). Só que além disso quero que ele formate de acordo com o que a pessoa for digitando, por exemplo, a pessoa digita:

120

depois que ela digitar o zero aparece a primeira barra, ficaria assim:
12/0

... seguindo a pessoa digita:
12/082

depois que ela digitar o dois aparece a segunda barra....
12/08/2

e o resto
12/08/2010.

tem um exemplo no link que vou colocar, só que é em java script e eu num entendi nada do que o cara fez. Vou colocar uma parte do código e o link para vocês entenderem melhor:

[url]http://www.mukirana.com/[/url] , vai em cadastre-se e lá tem um exemplo do que eu to falando, mas não com data e sim com CPF e CEP.

parte do código:
[code]
function mask_cpf(v){
v=v.replace(/\D/g,"");
v=v.replace(/(\d{3})(\d)/,"$1.$2");
v=v.replace(/(\d{3})(\d)/,"$1.$2");
v=v.replace(/(\d{3})(\d{1,2})$/,"$1-$2");
return v;
}

//depois ele chama ela assim:

onkeydown="mask(this,mask_cpf);
[code]

Se alguém souber fazer isso em java e puder me ajudar eu agradeço.
Obs.: já falaram para mim usar o jformattextfield, mas não consegui fazer o que eu quero, além de dizer que ele (jformattextfield) é chato pra caramba.....

10 Respostas

discorpio

Boa noite Davi.Jv

Que tal usar MaskFormatter e JFormattedTextField fazendo assim:

try {
        MaskFormatter mask = new MaskFormatter("##/##/####");
        mask.setPlaceholder("_");
  } catch (Exception ex){
        JOptionPane.showMessageDialog(null, ex.getMessage());
  }
  JFormattedTextField data = new JFormattedTextField(mask);

Detalhe é que sua máscara ficará com a formatação assim: “//____”, contudo basta somente digitar os números.

D

discorpio, já tentei fazer isso, funciona beleza, só que não do jeito que eu quero.
Desse jeito ai as barras ficam aparecendo antes mesmo da pessoa digitar algo, e não é assim que eu quero. eu quero que ela vai aparecendo de acordo com o que a pessoa digita, mas se não tiver jeito eu vou recorrer a esse seu exemplo.

discorpio

Boa noite Davi

Neste caso podemos também improvisar isso em java.

Basta que voce utilize o evento KeyListener do componente JTextField desta forma:

txtdata = new JTextField();
        txtdata.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e){
                JTextField text = (JTextField)e.getSource();
                if (text.getText().length() == 2 || text.getText().length() == 5){
                    text.setText(text.getText() + "/");
                }
            }
        });
D

discorpio, o seu código funcionou beleza, só que se a pessoa errar a data e for tentar corrigir o negócio bagunça tudo. Testa ai pra você ver.
Acontece o seguinte:

Você digita a data normal
10/10/2010

vamos supor que ela (pessoa) queria colocar 11/10/2010,

se ela apagar para poder arrumar, ela não irá conseguir. Depois que apagasse o 2 e a barra ela não consegue apaga o resto, e vira uma confusão. Se você for pro inicio da jtextfield tentar apagar usando o del, ele insere uma barra no final e etc.
acaba que no final se você tentar apagar todos os numeros vai ficar um bocado de barra ( ////// ) no jtextfield.

Mas do mesmo jeito muito obrigado, vou ver se consigo fazer algo para ver se ele para com essa locura.

Caso você ou outra pessoa tenha a solução ( para esse problema que surgiu) e quiser postar ai eu agradeço.

discorpio

Boa tarde Davi.Jv.

Como disse antes, apenas fiz de improviso e na hora, porém existem também a questão de se limitar a quantidade caracteres para 10 e também a validação das datas.

Assim sendo, quanto a questão de se limitar a quantidade de caracteres no JTextField, necessário é que voce crie a seguinte classe:

import javax.swing.text.*;

public class FixedLengthDocument extends PlainDocument {
    private int iMaxLength;

    public FixedLengthDocument(int maxlen) {
        super();
        iMaxLength = maxlen;
    }

    @Override
    public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException {
        if (str == null) {
            return;
        }

        if (iMaxLength <= 0)        // aceitara qualquer no. de caracteres
        {
            super.insertString(offset, str, attr);
            return;
        }

        int ilen = (getLength() + str.length());
        if (ilen <= iMaxLength)    // se o comprimento final for menor...
            super.insertString(offset, str, attr);   // ...aceita str
    }

}

Após criar essa classe, configure o seu JTextField assim:

txtdata = new JTextField();
txtdata.setDocument(new FixedLengthDocument(10));

Agora vamos a questão da validação das datas, criando o seguinte método booleano dentro da própria classe onde está o JTextField:

public Boolean validaData(String datatemp){
        Boolean ret;
        String data = datatemp.replace("/","");
        int dia = Integer.parseInt(data.trim().substring(0,2));
        int mes = Integer.parseInt(data.trim().substring(2,4));
        int ano = Integer.parseInt(data.trim().substring(4,8));
        int ultimoDiaMes[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
        if (ano < 1900){
            ret = false;
        } else if (mes < 0 || mes > 12) {
            ret = false;
        // Ano Bisexto    
        } else if (mes == 2 && ultimoDiaMes[mes] == 29 && (ano % 400 > 0 && (ano % 4 > 0 && ano % 100 == 0))){
            ret = false;
        } else if (dia < 0 && dia > ultimoDiaMes[mes]){
            ret = false;
        } else {
            ret = true;
        }
        if (ret == false) JOptionPane.showMessageDialog(null, "Data inválida");
        return ret;
    }

Agora dentro do evento KeyListener, vamos eliminar as barras duplas, assim:

txtdata = new JTextField();
txtdata.setDocument(new FixedLengthDocument(10));
txtdata.addKeyListener(new KeyAdapter() {
      @Override
       public void keyPressed(KeyEvent e){
                JTextField text = (JTextField)e.getSource();
                if (text.getText().length() == 2 || text.getText().length() == 5){
                    if (e.getKeyChar() == '/') {
                        text.getText().replaceAll("//", "/");
                    } else {
                       text.setText(text.getText() + "/");
                    }
                } else if (text.getText().length() == 10){
                    if (!validaData(text.getText())) text.setText("");
                }
        }
});
D

discorpio, o código deu certo porém continua com o erro que eu havia dito.
erro:
a pessoa digita uma data (exemplo 20/10/2009);

suponhamos que ela digitou a data errada, ela queria digitar (10/09/2009);

quando a pessoa tentar apagar a data (20/10/2009) que ela havia digitado, ela não consegue.

Ela só vai conseguir apagar até o 2 do ano 2009, ficando assim:
20/10

se ela tentar apagar o resto ela não consegue, e se ir para o inicio e tentar apagar do inicio pro fim tbm não dá certo, ele incrementa uma barra no final, ficando assim:
20/10/

a pessoa só vai conseguir apagar a data se selecionar tudo e apagar.

fora isso o código ficou show, mais uma vez muito obrigado, vou dar uma estuda no código para ver se entendo melhor ele e tentar descobrir com consertar isso.

Se você ou outra pessoa souber como consertar, fique a vontade.

D

Só aproveitando o seu código, teria alguma forma de a mensagem do JoptionPane aparecer logo que o campo data perdesse o foco?
Como ficaria o código?

discorpio

Boa tarde Davi.

Me desculpe a demora, porém só agora tive tempo de rever o código.

Realmente o código está com um erro de lógica, que quando voce pressiona barra normal repetidas vezes ele não se apaga, então neste caso vamos configurar o JTextField para ser digitado somente números e quando chegar nos índices 2 e 5 e colocar a barra normal automaticamente, e quando for pressionado qualquer outra tecla ele apague automaticamente, inclusive a barra normal, até mesmo dentro dos índices 2 e 5, isto porque ele já vai colocar automaticamente.

Outra coisa que eu pude perceber, de que o evento KeyReleased e melhor do que KeyPressed, na verdade o KeyPressed representa o KeyDown enquanto que o KeyReleased, o KeyUp, então vamos mudá-lo também, em resumo o seu código ficaria assim:

txtdata.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e){
                JTextField text = (JTextField)e.getSource();
                if (Character.isDigit(e.getKeyChar())){
                    if (text.getText().length() == 2 || text.getText().length() == 5){
                        text.setText(text.getText() + "/");
                    } else if (text.getText().length() == 10){
                        if (!validaData(text.getText())) text.setText("");
                    }
                } else {
                    text.setText(text.getText().substring(0, text.getText().length() -1));
                }
            }
 });

Quanto a mensagem só aparecer quando o JTextField perder o foco, neste caso voce terá que configurar da mesma forma com o código acima, os eventos FocusListener, podendo até deixar a mensagem de "Data inválida" dentro do método validaData, e utilizá-lo para retornar o foco para o JTextField editado. Em resumo, o seu código todo ficaria assim:

txtdata.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e){
                JTextField text = (JTextField)e.getSource();
                if (Character.isDigit(e.getKeyChar())){
                    if (text.getText().length() == 2 || text.getText().length() == 5){
                        text.setText(text.getText() + "/");
                    }
                } else {
                    if (text.getText().length() > 0){
                       text.setText(text.getText().substring(0, text.getText().length() -1));
                    }
                }
            }
 });
 txtdata.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e){
                JTextField text = (JTextField)e.getSource();
                if (!validaData(text.getText())){
                    text.setText("");
                }
            }
});

Contudo, se eu fosse voce eu preferiria não implementar esse FocusListener, ficaria com o primeiro código utilizando apenas o KeyListener, porque tentei setar o foco novamente ao JTextField editado, e estava dando erro, e caso de nós pesquisarmos mais.

Um abraço.

D

discorpio, o código faz exatamente ao contrario do que é pra fazer. Tipo, ele deixa que eu tecle apenas caracteres e não números.

txtdata.addKeyListener(new KeyAdapter() {  
             @Override  
             public void keyReleased(KeyEvent e){  
                 JTextField text = (JTextField)e.getSource();  
                 if (Character.isDigit(e.getKeyChar())){  
                     if (text.getText().length() == 2 || text.getText().length() == 5){  
                         text.setText(text.getText() + "/");  
                     } else if (text.getText().length() == 10){  
                         if (!validaData(text.getText())) text.setText("");  
                     }  
                 } else {  
                     text.setText(text.getText().substring(0, text.getText().length() -1));  
                 }  
             }  
 });

A respeito do que você falou de perde o focus vou manter o código de antes.

discorpio

Boa noite Davi.

Eu modifiquei a última linha, assim:

txtdata.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e){
                JTextField text = (JTextField)e.getSource();
                if (Character.isDigit(e.getKeyChar())){
                    if (text.getText().length() == 2 || text.getText().length() == 5){
                        text.setText(text.getText() + "/");
                    } else if (text.getText().length() == 10){
                        if (!validaData(text.getText())) text.setText("");
                    }
                } else {
                    // Aqui foi acrescentado esta verificação.
                    if (text.getText().length() > 0){   
                       text.setText(text.getText().substring(0, text.getText().length() -1));   
                    }                 
               }
            }
 });

Esse código só permite a digitação de números.

Criado 20 de outubro de 2010
Ultima resposta 24 de out. de 2010
Respostas 10
Participantes 2