Thread.sleep travando programinha

3 respostas
F

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?

3 Respostas

diego_qmota

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.

F

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..

//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);

   }


    }
diego_qmota

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…

Criado 18 de fevereiro de 2011
Ultima resposta 18 de fev. de 2011
Respostas 3
Participantes 2