Problemas com DocumentListener

Pintou uma dúvida meio besta aqui, pois há um tempão que não lido com isso: Eu preciso ter TODOS JTexfields responsivos, ou seja, a cada digitação do usuário num campo, uma(ou mais) fórmula(s) será(ão) executada, e um campo em outro formulário será atualizado.
Por exemplo, em dois JTextFields para atualizar uma fórmula:

[code]
final JTextField areaEdField=new JTextField(6);
final JTextField areaTotField=new JTextField(9);
areaEdField.getDocument().addDocumentListener(new DocumentListener(){
String s;
public void insertUpdate(DocumentEvent e){
if(areaEdField.getText()!=null&&areaTotField.getText()!=null){
BigDecimal decimalEdificada = new BigDecimal(areaEdField.getText());
decimalEdificada = decimalEdificada.setScale(4, RoundingMode.HALF_UP);
BigDecimal decimalTerreno = new BigDecimal(areaTotField.getText());
decimalTerreno = decimalTerreno.setScale(4, RoundingMode.HALF_UP);
BigDecimal result=decimalEdificada.divide(decimalTerreno,4,RoundingMode.HALF_UP);
s=String.valueOf(result);
fracaoIdeal.setText(s);
}
else
fracaoIdeal.setText("1.00");
}
public void removeUpdate(DocumentEvent e){
s = areaEdField.getText();
if(s.length() &lt 1)
fracaoIdeal.setText("1.00");
}
public void changedUpdate(DocumentEvent e){}
});//fim da inner class de areaEdField

		areaTotField.getDocument().addDocumentListener(new DocumentListener(){
              String s;                   
     public void insertUpdate(DocumentEvent e){
    	if(areaEdField.getText()!=null&&areaTotField.getText()!=null){
    		BigDecimal decimalEdificada = new BigDecimal(areaEdField.getText()); 

decimalEdificada = decimalEdificada.setScale(4, RoundingMode.HALF_UP);
BigDecimal decimalTerreno = new BigDecimal(areaTotField.getText());
decimalTerreno = decimalTerreno.setScale(4, RoundingMode.HALF_UP);
BigDecimal result=decimalEdificada.divide(decimalTerreno,4,RoundingMode.HALF_UP);
s=String.valueOf(result);
fracaoIdeal.setText(s);
}
else
fracaoIdeal.setText("1.00");
}
public void removeUpdate(DocumentEvent e){
s = areaTotField.getText();
if(s.length() &lt 1)
fracaoIdeal.setText("1.00");
}
public void changedUpdate(DocumentEvent e){}
});//fim da inner class de areaTotField
[/code]
O troço fica uma carroça, fora quando não rola uma NumberFormatException e tudo mais pq acaba sendo digitado um num gigantesco pq o usuário acha q não digitou nada.Alguém tem idéia melhor?

Dá para você relaxar o requisito e estabelecer que a fórmula só será recalculada quando você passar o foco para outro campo? Do jeito que você fez, a cada vez que você digita qualquer coisa (inclusive lixo), a fórmula é recalculada.

Você pode colocar o cálculo da fórmula em outra thread.

Esse é o meu problema!!! :frowning:
Eu tinha feito exatamente como vc falou(funcionava 100%), mas o problema é que essa fórmula participa do cálculo de uma outra fórmula.Aí, quando alguém mudava algo em areaEdField(o primeiro componente da fórmula), não atualizava, só se o segundo fosse mexido também(E vc nem imagina o tam da interface, + de 100 componentes).

Boa idéia. (É só você tratar esses NumberFormatExceptions direito, já que vi que você pega o valor direto do JTextField, o que nunca é boa idéia. )

Não saquei, dá um exemplo.

Não é mesmo, mas é protótipo, o importante são os cálculos(se os numeros forem digitados certos), depois eu ponho uma validação nele, mas se não está responsivo assim, imagine quando todos estiverem sendo verificados/validados/alterados.

Coloque as linhas que fazem os cálculos em métodos. Então nos listeners faça:

new Thread( new Runnable() {
    public void run() {
        meuMetodo();
    }
} ).start();

Isso eu saquei(já tinha até reescrito para coisas como atualizarBlablabla…), mas não haveria riscos de eu ter problemas de desempenho, considerando que são muuitos componentes.

Se bem que se eu controlar a concorrência pode funcionar! :smiley:
Valeu Lipe.

Uma forma legal de avisar ao usuário que houve uma NumberFormatException (fora usar um campo de entrada formatado, mas o JFormattedTextField é um @#$% para usar corretamente) é deixar o fundo (setBackground) com uma outra cor - digamos vermelho, ou então deixar a borda com uma outra cor (setBorder (BorderFactory.createMatteBorder(3, 3, 3, 3, Color.RED)).

Hahah, fico feliz de saber que não sou o único com problemas com o JFormattedTextField…
E eu já tava usando o setBackground para salientar o fundo quando dá m, mas só na fórmula final.É um saco ter que deixar todos os componentes atualizáveis, a sun deveria ter projetado um "JLiveTextField" para isso, ficaria beem mais tranquilo.
Ah, usando + ou - assim:

componente.getDocument().addDocumentListener(new DocumentListener(){ String s; public void insertUpdate(DocumentEvent e){ if(componente.getText()!=null&&componente2.getText()!=null){ new Thread( new Runnable() { public void run() { atualizarFracaoIdeal(componente.getText(),componente2.getText()); } } ).start(); } else fracaoIdeal.setText("1.00"); } public void removeUpdate(DocumentEvent e){ s = componente.getText(); if(s.length() &lt 1) fracaoIdeal.setText("1.00"); } public void changedUpdate(DocumentEvent e){} });//fim da inner class de componente
funciona Ok a atualização, agora eu vou tratar o problema dos NumberFormat Exception.
Thingol, a minha sorte é que os dados não serão inseridos em nenhum lugar(é uma folha de cáculo para o IPTU), pois é só calcular, e depois passar para o papel(é feito manualmente!).

É mesmo…damn…
Tá tudo funcionando ok, mas os NFException me preocupam.
Eu tô fazendo uma classe que extends JTextField e lá eu não deixo digitar letras e tal.É um saco que a Sun não tenha desenvolvido TextFields especiais para atualização “justInTime” e melhor resposta ao usuário.

Ah, esqueci de pôr aqui algo importante:
Quando se usa um DocumentListener em cada componente, uma simples obtenção de foco já dispara uma NFException, pois será passado um null do componente ainda não preenchido.É necessário ou inicializar cada componente, ou tratar cada componente com esse null. :wink: