Thread.sleep travando programinha

Pessoal, estou com o seguinte problema … o usuário digita o TextField o valor dos segundos… criei um for decrementando esses segundos, os segundos eu estou usando o Thread.sleep… so que é o seguinte… digita segundo… quando click no botão … ele começa a decrementar… mas tem um problema… o programa fica travado …
como faço p programa não travar?

Você deve criar um Thread isolado, somente para atuar neste JTextField.
Senão, você interfere no Thread principal da janela.


//método dentro da sua janela
public void apertoBotaoDecrementarSegundos() {

//Chamando esse processo em uma nova thread, você evita o travamento da thread principal (da janela SWING):
Thread novaThreadDecrementar = new Thread() {

   public void run() {

     while (...) {   //enquanto texto no jtextfield é maior que 0
       
       //qualquer código que altera elementos da janela SWING, você insere na pilha do thread da janela
       //você até poderia alterar diretamente, mas alguns componentes SWING apresentam travamentos, então rezam as boas práticas que qualquer alteração de componente SWING deve ser efetuada na Thread principal.
       EventQueue.invokeLater(new Runnable() {
         public void run() {
             //insira aqui o código para decrementar o jtextfield.
         }
       });

       sleep( 1000 );  //sleep para a thread adormecer por 1 segundo.

   }

}
novaThreadDecrementar.start();  //inicia execução paralela da nova thread e não trava a thread principal.


} //fim da função

Com a execução desse código você terá “duas Threads” executando ao mesmo tempo (há mais threads executando para o seu programa na JVM, mas para fins de entendimento, considere somente as que você está operando programaticamente):

***** Thread da janela SWING
**| Thread que você criou (novaThreadDecrementar) - pausada

Se você parar ou pausar a segunda thread, você não interrompe a primeira.

O que você estava fazendo antes, era pausar a
*****| Thread da janela SWING
sem querer.

Tentei aqui mas não foi, veja o meu código como tá… não da para criar dois public void run. acho que fiz alguma coisa errada…

[code] //Variaveis.
public int entradaCampo1 = 0,entradaCampo2 = 0, contador = 0, total = 0;
String campoSegundos1 = “”, campoSegundos2 = “”;

 //Inicial o método
public void calcular(String horas, String minutos) throws Exception{

try{

/Horas/ entradaCampo1 = 3600 * Integer.parseInt(horas);

    }catch(NumberFormatException b){

        if(horas == null){
            entradaCampo1 = 0;
        }
    }

try{
     /*Minutos*/entradaCampo2 = 60 * Integer.parseInt(minutos);
}catch(NumberFormatException c){

    if(minutos == null){
       entradaCampo2 = 0;
    }
}

contador = entradaCampo1 + entradaCampo2;

//Inicia o laço da thread.
for( ; contador >= 0 ; contador–){

   try{

       Thread.sleep(1000);

   }catch(InterruptedException e){

       JOptionPane.showMessageDialog(null, "Erro");

   }

   if(contador == 0){
   try{

       Runtime.getRuntime().exec("calc.exe");
   }catch(IOException a){

       JOptionPane.showMessageDialog(null, "Erro Na execução do comando.");

   }

   }
  System.out.println(contador);

}

}[/code]

Cara, coloca o código como estava antes, ou seja, quando você tentava dar o sleep e travava a janela.

Assim está bastante confuso…

A idéia é você criar uma thread quando for iniciar a operação.

Dentro do método run dessa nova thread, você insere todo o código de diminuir o tempo do JTextField.

Sobre o “run dentro do outro run”:
Somente se você alterar alguma coisa na janela, você vai colocar dentro da thread recém criada: uma mensagem para a thread principal: (abre EventQueue.invokeLater … novo objeto Runnable (pai da classe Thread) … novo método run … o código que atualiza a interface gráfica (campos de texto, labels, etc) … fecha EventQueue ).
Siga os comentários para você entender a estrutura

//INICIA MÉTODO RUN DA NOVA THREAD PARALELA
public void run() {

final StringBuilder tempo = new StringBuilder();

while (...) {     //loop que fica executando até zerar o tempo

//DENTRO DO MÉTODO RUN DA NOVA THREAD PARALELA
//CÓDIGO PARA EXECUTAR A OPERAÇÃO: DECREMENTAR TEMPO
//...
//...


//Enviando mensagem para a thread principal (SWING) para atualizar a interface gráfica com o tempo decrementado em 1 segundo.
//você manda ser executada assim que possível um Runnable (pai da classe Thread), que será executada dentro da thread principal (SWING).
EventQueue.invokeLater(new Runnable() {  
   //aqui iniciamos um Runnable - equivalente a thread -- que será "anexado" a thread principal
   public void run() {  
      jTextFieldTempo.setText(tempo.toString());      

   }}  
);  //aqui acaba o envio de mensagem para a thread principal. Voltamos a thread paralela que fica decrementando o tempo.


sleep(1000);  //pausa a nova thread paralela por 1 segundo.

}

//FINALIZA MÉTODO RUN DA NOVA THREAD PARALELA
//...

}
//AQUI VOLTAMOS A THREAD PRINCIPAL (SWING).

O código para executar na thread principal eu deixei logo acima. Só use isso se for atualizar elementos da janela, não coloque mais nada dentro de EventQueue…