Binding a JTextField e poder limitar comprimento

31 respostas
T

Boa noite pessoal

Gostaria de saber se alguém sabe como limitar o comprimento do String dentro de JTextField, so que o mesmo está Binding (vinculado) a uma propriedade de um objeto?

Eu até desenvolvi uma classe que implementa o Document para fazer isso, só que quando o Bean Binding é inicializado, ele substitui o meu Document.

desde já agradeço

31 Respostas

T

Bom dia pessoal?

alguém utiliza por acaso Beans Binding neste forum?

grato

M

Voce que criou esse Document para o binding? se for…

Coloque o limitador nele mesmo.

T

Eu até coloco esse document,
so que o binding substitui pelo dele

M

Então… mas voce que criou esse Document para Binding?

Por que voce não pega o Document do JTextField depois do binding substitui-lo e coloca seu limitador nele?

T

Mas o Binding necessita do Document dele para controlar a transferencia dos valores.

M

Não to falando pra substituir.
To falando pra adicionar sua lógica de limitação nele.

T

Mas como?

O binding é feito atraves de um Factory e eu não sei qual classe ele utiliza para fazer isso.

vou tentar achar a classe q é montada.

ou existe outra maneira?

M

Ahh… eu pensei que voce tinha feito essa classe…

Mas…

Voce pode pegar o Document do JTextField e adicionar um DocumentListener nele com essa lógica.

M

Depois do binding pegue o Document e adicione algo assim…

textField.getDocument().addDocumentListener(new DocumentListener(){
//Lógicas aqui
public void insertUpdate(DocumentEvent e){
}
public void removeUpdate(DocumentEvent e){
}
public void changedUpdate(DocumentEvent e){
}
});

PS: Eu nunca precisei fazer isso só to pesquisando na API e te falando.

http://java.sun.com/j2se/1.3/docs/api/javax/swing/JTextField.html
http://java.sun.com/j2se/1.3/docs/api/javax/swing/text/Document.html
http://java.sun.com/j2se/1.3/docs/api/javax/swing/event/DocumentListener.html
http://java.sun.com/j2se/1.3/docs/api/javax/swing/event/DocumentEvent.html

T

Boa Ideia cara

muito obrigado, não tinha reparado que tinha listeners no Document.

grato e desculpe qualquer coisa

T

Tentei montar o travamento no evento insertUpdate do listenner DocumentListener, só que não deu muito certo não pois ele nao tem retorno de validação e tb não funciona com exception.

fiz assim:

new DocumentListener() {

            public void insertUpdate(DocumentEvent e) {
                if (!(e.getDocument().getLength() < EstadoController.LENGTH_SIGLA &&
                        e.getDocument().getLength() + e.getLength() < EstadoController.LENGTH_SIGLA)){
                    throw new IllegalArgumentException();
                }
            }

            public void removeUpdate(DocumentEvent e) {
                
            }

            public void changedUpdate(DocumentEvent e) {
                
            }
        }

e a documentação fala que o document é imutavel durante o evento por ser threadsafe.

teria alguma sugestão?

T

Achei esta documentação que ajudou muito a montar o q eu queria.

https://java.sun.com/docs/books/tutorial/uiswing/components/generaltext.html#doclisteners

falow

T

Afff… quase deu certo.

descobri que a classe que o beanbinding altera tb é o DocumentFilter com a classe JTextComponentAdapterProvider
aff… vou ter que estudar mais um pouco e terei q alterar essa classe tb…
aff
rs

M

Nossa… mas continue com os estudos que no final voce consegue.

T

Mark

estive estudando o componente BeansBinding e ele tem uma classe que valida os dados que são inseridos, e tem tb um listener para que possa ser feito alguma coisa.

no meu caso no validator, coloquei para retornar um erro quando for superior a quantidade de caracteres, utilizando a classe Result do BeansBinding.

e Adicionei um listener e no evento de falha de sincronismo eu mostro uma mensagem.

A validação funciona pois não altera o Bean que estou vigiando, so que visualmente não funciona pois o JTextField ainda continua exibindo os caracteres que passaram do limite.
vc ja trabalhou com o BeansBindig?

Se não trabalhar, como vc faz a vinculação dos componentes swing com os beans?

grato

M

Então… no meio dos meus projetos eu acho que reinventei varias rodas então eu uso um objeto que eu mesmo criei…

Chamo de ComponentBind passo JTextComponents e FieldResovers para ele e quando for atualizer o objeto eu faço

binder.updateObject(objectDoTipo);

E para atualizar a view chamo o método assim:

binder.updateView(objectDoTipo);
T

Você utiliza então uma idéia de MVC ou MVP?

M

Sinceramente não sei xD

Eu separo assim:

model > models
dao > DAO generica e conexao com banco
view > Swing

Eu ligo o model com a view atraves do Binder que criei
E uso a dao para mandar pro banco.

Eu acho que é MVC.

Eu não estudei MVC e MVP.

T

Em que momento vc faz a validação dos dados?

M

Então… é que todos os campos Strings no meu bd estão como varchar<255> então não me preocupo com o tamanho, os campos ints e doubles são convertidos pelo binder e caso tenha algo errado (Por exemplo letras) ele lança uma Exception que eu posso tratar para validação.

E tem outra coisa meu Binder não mantem sincronizado os dois… apenas quando chamo os métodos para atualizar ou a view com o objeto ou o objeto com a view eu sei os valores.

T

Eu quis dizer em relação a validação de valores, como se um campo de percentual aceita uma determinada faixa, etc

M

Todos meus campos não tem essas exigencias… mas de qualquer modo no conversor do binder seria possivel de colocar isso… por que ao converer o valor poderia lançar uma Exception.

T

Acho q não está me entendendo

quando um campo exige um determinado valor tipo, quantidade não pode ser inferior a 1, essa validação vc faz no view, ou vc faz no model?

M

Então… voce que não me entendeu

No meu binder eu tenho a opção de passar um formatter meu que a interface é a seguinte

public interface Formatter{
public Object parseString(String arg1);
public String format(Object obj1);
}

Caso o método retorne uma Exception eu lanço ela ao método que chamou o update do binder.

Tipo assim:

Formatter valorMaiorQueUm = new Formatter(){
@Override
public String format(Object obj1){
return Integer.toString((Integer)obj1);//Eu sei que nessa coluna ele retorna sempre Integers
}
@Override
public Object parseString(String arg1){
int obj;
try{
obj = Integer.parseInt(arg1);
}catch(Exception e){
throw new RuntimeException(arg1+": Este valor não é um numero inteiro valido");
}

if(obj < 1)
throw new RuntimeException(arg1+": O valor não pode ser menor que um");

return obj;
}
}
T

O problema que eu encontro nesta abordagem é que o usuários só vai saber que deu erro quando é feito a transferência de dados, depois que ele já preencheu toda a tela.

M

É… eu sei disso…

Mas mes campos não precisam de validação desse tipo, apenas para converter para numeros alguns valores.

Mas pretendo fazer algo para validar mesmo, tava pensando nisso a um tempo.

M

E eu não sei se é tão ruim assim quando o usuario processa os dados aparece um campo em vermelho pois está com algo errado.

T

Bom num sistema baseado na web, geralmente a validação é feita somente no retorno, mas numa aplicação desktop, acredito que o usuário tenha que saber antes pois ele, em geral, espera mais agilidade numa aplicação desktop.

M

E o engraçado é que tenho um sistema na web para um cliente com JSF e a validação é na hora.
=/

Mas eu pretendo implementar algo em breve com essa finalidade para meus sistema desktop.

T

Bom eu estou estudando o beansbinding e com ele posso colocar validators, que impedem que seja colocado um valor inválido, e tb coloquei um extended by org.jdesktop.beansbinding.AbstractBindingListener no metodo syncFailed e nele eu faço o bind efetuar um refresh ai ele restaura o último valor válido. E parece que ficou legal.
Vou testar mais e ver se existe outras maneiras.

falow

R

EStou com o mesmo problema que vc tebosoftware, criei uma classe bacaninha extendendo o document… onde passo por parametros a quantidade de caracteres que o textField vai aceitar, se é tudo Upper ou Lower e se é alfanuméricou ou numérico.
O problema é quando uso binding no textField… pois perde toda formatação do document que eu havia criado…

Você já conseguiu uma solução razoável para isso???

Minha FixedLengthDocument

public class FixedLengthDocument extends PlainDocument
{
    private int limit = -1;
    private int fixedLengthDocumentMode = -1;
    private ArrayList&lt;String&gt; noInsertCharsVerify = new ArrayList&lt;String&gt;();
    private String[] listNoInsertChars = new String[]{};
    public static final int LENGTH_UNLIMITED = -1;

    public static final int TO_UPPER = 1;
    public static final int TO_LOWER = 0;
    public static final int TO_DEFAULT = -1;
    /**
     *
     * @param maxlen
     */
    public FixedLengthDocument(int limit)
    {
        super();
        this.limit = limit;
        this.fixedLengthDocumentMode = TO_DEFAULT;
        this.listNoInsertChars = new String[]{};
        this.noInsertCharsVerify = new ArrayList&lt;String&gt;();
    }
    public FixedLengthDocument(int limit, int fixedLengthDocumentMode)
    {
        super();
        this.limit = limit;
        this.fixedLengthDocumentMode = fixedLengthDocumentMode;
        this.listNoInsertChars = new String[]{};
        this.noInsertCharsVerify = new ArrayList&lt;String&gt;();
    }
    public FixedLengthDocument(int limit, int fixedLengthDocumentMode, String[] listNoInsertChars)
    {
        super();
        this.limit = limit;
        this.fixedLengthDocumentMode = fixedLengthDocumentMode;
        this.listNoInsertChars = listNoInsertChars;
        System.out.println("listNoInsertChars:" + listNoInsertChars.length);
        this.noInsertCharsVerify = new ArrayList&lt;String&gt;();
        for(int i=0; i&lt;listNoInsertChars.length; i++)
            this.noInsertCharsVerify.add(listNoInsertChars[i]);
    }

    @Override
    public void insertString(int offset, String str, AttributeSet attr)
                    throws BadLocationException
    {
        if(!noInsertCharsVerify.isEmpty())
            for( int i = 0; i &gt;&lt; str.length(); i++ )
                if(noInsertCharsVerify.contains( String.valueOf(str.charAt(i))) )
                    return;
        if((limit&gt;LENGTH_UNLIMITED) && (getLength() + str.length()) &lt;= limit)
        {
            switch(fixedLengthDocumentMode)
            {
                case TO_UPPER:
                    super.insertString(offset, str.toUpperCase(), attr);
                break;
                case TO_LOWER:
                    super.insertString(offset, str.toLowerCase(), attr);
                break;
                case TO_DEFAULT:
                    super.insertString(offset, str, attr);
                break;
            }
        }
        else
        {
            if(limit ==LENGTH_UNLIMITED)
            {
                switch(fixedLengthDocumentMode)
                {
                    case TO_UPPER:
                        super.insertString(offset, str.toUpperCase(), attr);
                    break;
                    case TO_LOWER:
                        super.insertString(offset, str.toLowerCase(), attr);
                    break;
                    case TO_DEFAULT:
                        super.insertString(offset, str, attr);
                    break;
                }
            }
        }
    }

    @Override
    public void remove(int offs, int len) throws BadLocationException
    {
        super.remove(offs, len);
    }
}
Criado 3 de dezembro de 2008
Ultima resposta 4 de abr. de 2011
Respostas 31
Participantes 3