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…