Problema com DocumentListener quando um JtextField tem que atualizar outro[RESOLVIDO]

4 respostas
VantuilJose

Pessoal tô com um problema no seguinte código:

txtDescAbsoluto.getDocument().addDocumentListener(new DocumentListener() {
            public void insertUpdate(DocumentEvent e) {
                atualizaPreco();
            }
            public void removeUpdate(DocumentEvent e) {
                atualizaPreco();
            }
            public void changedUpdate(DocumentEvent e) {}
            public void atualizaPreco(){
                cupom.setDescAcres(txtDescAbsoluto.getNumero());
                double desc = txtDescAbsoluto.getNumero() * 100/ cupom.getSubTotal();
                txtDescRelativo.setNumero(desc);
            }

        });
txtDescRelativo.getDocument().addDocumentListener(new DocumentListener() {

            public void insertUpdate(DocumentEvent e) {
                atualizaPreco();
            }

            public void removeUpdate(DocumentEvent e) {
                atualizaPreco();
            }

            public void changedUpdate(DocumentEvent e) {

            }

            public void atualizaPreco(){
                double desc = txtDescRelativo.getNumero()*cupom.getSubTotal()/100;
                cupom.setDescAcres(desc);
                txtDescAbsoluto.setNumero(desc);
            }

        });

O que tô tentando fazer é atualizar um campo com porcentagem quando o usuário muda um valor e atualizar o valor quando ele muda a porcentagem. Mas parece que o Java cria um lock quando tem algum listener em execução....

Obetenho o seguinte erro:
Exception occurred during event dispatching:
java.lang.IllegalStateException: Attempt to mutate in notification
        at javax.swing.text.AbstractDocument.writeLock(AbstractDocument.java:1323)
        at javax.swing.text.AbstractDocument.remove(AbstractDocument.java:570)
        at zcm.swing.ZDecimalField$DecimalDocument.insertStringConfigurada(ZDecimalField.java:139)
        at zcm.swing.ZDecimalField.setNumero(ZDecimalField.java:97)
        at emissor.TelaFechaVenda$5.atualizaPreco(TelaFechaVenda.java:183)
        at emissor.TelaFechaVenda$5.removeUpdate(TelaFechaVenda.java:173)
        at javax.swing.text.AbstractDocument.fireRemoveUpdate(AbstractDocument.java:243)
        at javax.swing.text.AbstractDocument.handleRemove(AbstractDocument.java:608)
        at javax.swing.text.AbstractDocument.remove(AbstractDocument.java:576)
        at zcm.swing.ZDecimalField$DecimalDocument.insertStringConfigurada(ZDecimalField.java:139)
        at zcm.swing.ZDecimalField.setNumero(ZDecimalField.java:97)
        at emissor.TelaFechaVenda$4.atualizaPreco(TelaFechaVenda.java:162)
        at emissor.TelaFechaVenda$4.removeUpdate(TelaFechaVenda.java:156)
        at javax.swing.text.AbstractDocument.fireRemoveUpdate(AbstractDocument.java:243)
(...)

Qual a melhor forma de contornar esse erro?
Alguem tem alguma idéia que possa me ajudar?
Já usei um código com invokeLater, é uma boa opção?

4 Respostas

C

Isso ocorre porque está ocorrendo uma execução circular.

Uma maneira é fazer cada método atualizaPreco ignorar o outro.

Poderia ser algo como:

private boolean locked;
	
public void atualizaPreco1() {  
   if (!locked) {
      locked = true;
      ...
      locked = false;
   }
}

public void atualizaPreco2() {  
   if (!locked) {
      locked = true;
      ...
      locked = false;
   }
}

...

 txtDescAbsoluto.getDocument().addDocumentListener(new DocumentListener() {  
   public void insertUpdate(DocumentEvent e) {  
      atualizaPreco1();  
   }  
   public void removeUpdate(DocumentEvent e) {  
      atualizaPreco1();  
   }  
   public void changedUpdate(DocumentEvent e) {
      atualizaPreco1();  
   }     
});  

txtDescRelativo.getDocument().addDocumentListener(new DocumentListener() {  
   public void insertUpdate(DocumentEvent e) {  
       atualizaPreco2();  
   }  
   public void removeUpdate(DocumentEvent e) {  
       atualizaPreco2();  
   }  
   public void changedUpdate(DocumentEvent e) {  
       atualizaPreco2();  
   }     
});

E não esquece de usar no public void changedUpdate(DocumentEvent e) também

VantuilJose

Vou testar aqui depois posto…

O que o changedUpdate(DocumentEvent e) faz? em que momento ele é chamado?

C

VantuilJose:
Vou testar aqui depois posto…

O que o changedUpdate(DocumentEvent e) faz? em que momento ele é chamado?

Oi.

Desculpa, no seu caso não precisa mesmo usar esse método. Ele é executado apenas se o document for um StyledDocument e se alterar o estilo do documento.

abs

VantuilJose

Blz…
É por que tinha até testado pra ver se ele iria ser chamado em algum momento e não foi…

Entendi a jogado do lock lá… hehehe
Simples e eficaz…
Funcionado perfeitamente…
Obrigado…

Criado 18 de maio de 2010
Ultima resposta 19 de mai. de 2010
Respostas 4
Participantes 2