[Resolvido] Timer regressivo, como implementar?

Boa noite,

Preciso implementar um timer que receba um valor de uma outra variável, e comece uma contagem regressiva em cima desse valor, sendo exibido na tela.

Andei fazendo uma busca no fórum e achei algo para iniciar um timer progressivo a partir do 0, mas não esse que eu preciso.

Alguem pode me ajudar?

Abraços,

ja pensou em fazer um for que vai diminuindo o valor dessa variável a cada loop?

deve haver alguma classe utilitária pra isso, mas não conheço hehehe…

a idéia básica é: public static void main(String[] args){ int segundos = 10; try{ for (int i = segundos; i > 0; i--){ System.out.println(i + " segundos"); Thread.sleep(1000); // 1 segundo } System.out.println("Terminei!"); } catch (InterruptedException e){ System.out.println("Interromperam meu sono!"); } }Sei que dizem que usar Thread.sleep() é péssimo, mas foi o jeito mais simples que encontrei pra criar um exemplo :slight_smile:

Fiz um exemplo:

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

/**
 *
 * @author Henrique Ferreira da Silva
 */
public class Cronometro {

    private Timer cronometro;
    private DateFormat formato = new SimpleDateFormat("HH:mm:ss");
    private Calendar calendario = Calendar.getInstance();
    private final byte contagem;
    public static final byte PROGRESSIVA = 1;
    public static final byte REGRESSIVA = -1;

    public Cronometro(int ano, int mes, int dia, int horas, int minutos, int segundos, byte tipoContagem) {
        this.cronometro = new Timer();
        calendario.set(ano, mes, dia, horas, minutos, segundos);
        this.contagem = tipoContagem;
    }

    public void cronometro() {
        TimerTask tarefa = new TimerTask() {

            @Override
            public void run() {
                System.out.println(getTime());
            }
        };
        cronometro.scheduleAtFixedRate(tarefa, 0, 1000);
        this.cronometro = null;
    }

    public String getTime() {
        calendario.add(Calendar.SECOND, contagem);
        return formato.format(calendario.getTime());
    }

    public static void main(String[] args) {
        Cronometro contagem = new Cronometro(0, 0, 0, 10, 30, 5, REGRESSIVA);
        contagem.cronometro();
    }
}

Note que no construtor da classe você pode passar como parâmetro: o ano, mês, dia, horas, minutos e segundos para iniciar o timer e ainda escolher se deseja contagem regressiva ou progressiva.

No exemplo, o cronometro inicia em 10 horas, 30 minutos e 5 segundos.

:thumbup:

segue solução

Amigo, esses dois códigos acima funcionam, mas pelo que eu entendi da sua necessidade, esse timer terá de roda em paralelo com uma outra aplicação certo?

O melhor é criar uma Thread.

Observe o código:
Talvez tenha algum erro de sintaxe, mas basicamente é isso:


class Timer {


  public static void main(String[] argumentos){
    // instancia uma thread, passando como construtor uma implementação de runnable.
    //runnable é uma interface, que implementa o metodo run, quando a thread é statada(.start();), o método run() é executado.
    // o parâmetro do construtor da classe ExecucaoDoThread é o número que vai ser decrescido até 0
    Thread t = new Thread(new ExecucaoDoThread(10));
    t.start();
  }




  class ExecucaoDoThread implements Runnable{
    
    private int num;      

    public ExecucaoDoThread(int num){
      //o num vai receber o numero que vai ser descrescido até 0;
      this.num = num;
    }
    
    @Override
    public void run(){
      //aqui vai o código que será executado pela thread
      //cria um jframe e seta seu tamanho
      JFrame frame = new JFrame();
      frame.setSize(200,200);

      //cria uma jlabel, adiciona no frame e chama o metodo do, passando essa label como parametro
      JLabel label = new JLabel();
      frame.add(label);
      go(label);
    }

    public void go(JLabel label){
      //faz um for que vai de num até 0, no passo -1.
      //cada loop do for, troca o valor do label por i, e espera 1 segundo ( utilizando o metodo static Thread.sleep(); e passando o tempo em millis que deverá aguardar
      for(int i = num;i>=0;i--){
        try{
          label.setText(i+"");
          Thread.sleep(1000);
        }catch(Exception ex){}
      }
    }

  }


}

Acho que vai funcionar…
qualquer dúvida, procure tutoriais sobre Threads ou me mande uma mensagem que eu volto a explicar.

[quote=digaoneves]ja pensou em fazer um for que vai diminuindo o valor dessa variável a cada loop?

deve haver alguma classe utilitária pra isso, mas não conheço hehehe…

a idéia básica é: public static void main(String[] args){ int segundos = 10; try{ for (int i = segundos; i > 0; i--){ System.out.println(i + " segundos"); Thread.sleep(1000); // 1 segundo } System.out.println("Terminei!"); } catch (InterruptedException e){ System.out.println("Interromperam meu sono!"); } }Sei que dizem que usar Thread.sleep() é péssimo, mas foi o jeito mais simples que encontrei pra criar um exemplo :)[/quote]

[quote=ByIvo]Amigo, esses dois códigos acima funcionam, mas pelo que eu entendi da sua necessidade, esse timer terá de roda em paralelo com uma outra aplicação certo?

O melhor é criar uma Thread.

Observe o código:
Talvez tenha algum erro de sintaxe, mas basicamente é isso:


class Timer {


  public static void main(String[] argumentos){
    // instancia uma thread, passando como construtor uma implementação de runnable.
    //runnable é uma interface, que implementa o metodo run, quando a thread é statada(.start();), o método run() é executado.
    // o parâmetro do construtor da classe ExecucaoDoThread é o número que vai ser decrescido até 0
    Thread t = new Thread(new ExecucaoDoThread(10));
    t.start();
  }




  class ExecucaoDoThread implements Runnable{
    
    private int num;      

    public ExecucaoDoThread(int num){
      //o num vai receber o numero que vai ser descrescido até 0;
      this.num = num;
    }
    
    @Override
    public void run(){
      //aqui vai o código que será executado pela thread
      //cria um jframe e seta seu tamanho
      JFrame frame = new JFrame();
      frame.setSize(200,200);

      //cria uma jlabel, adiciona no frame e chama o metodo do, passando essa label como parametro
      JLabel label = new JLabel();
      frame.add(label);
      go(label);
    }

    public void go(JLabel label){
      //faz um for que vai de num até 0, no passo -1.
      //cada loop do for, troca o valor do label por i, e espera 1 segundo ( utilizando o metodo static Thread.sleep(); e passando o tempo em millis que deverá aguardar
      for(int i = num;i>=0;i--){
        try{
          label.setText(i+"");
          Thread.sleep(1000);
        }catch(Exception ex){}
      }
    }

  }


}

Acho que vai funcionar…
qualquer dúvida, procure tutoriais sobre Threads ou me mande uma mensagem que eu volto a explicar.[/quote]

Então, esse timer roda em paralelo sim, é uma tabela com diversas linhas, onde cada uma levará um contador próprio, e um dos horários para esse cálculo será o horário atual.

Estava verificando essa solução utilizando threads, porém não seria até mais seguro utilizar um servidor que seta o relógios dos computadores (para o usuário não mexer) e usar o horário do pc como base pra cada cálculo?

[quote=InicianteJavaHenrique]Fiz um exemplo:

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

/**
 *
 * @author Henrique Ferreira da Silva
 */
public class Cronometro {

    private Timer cronometro;
    private DateFormat formato = new SimpleDateFormat("HH:mm:ss");
    private Calendar calendario = Calendar.getInstance();
    private final byte contagem;
    public static final byte PROGRESSIVA = 1;
    public static final byte REGRESSIVA = -1;

    public Cronometro(int ano, int mes, int dia, int horas, int minutos, int segundos, byte tipoContagem) {
        this.cronometro = new Timer();
        calendario.set(ano, mes, dia, horas, minutos, segundos);
        this.contagem = tipoContagem;
    }

    public void cronometro() {
        TimerTask tarefa = new TimerTask() {

            @Override
            public void run() {
                System.out.println(getTime());
            }
        };
        cronometro.scheduleAtFixedRate(tarefa, 0, 1000);
        this.cronometro = null;
    }

    public String getTime() {
        calendario.add(Calendar.SECOND, contagem);
        return formato.format(calendario.getTime());
    }

    public static void main(String[] args) {
        Cronometro contagem = new Cronometro(0, 0, 0, 10, 30, 5, REGRESSIVA);
        contagem.cronometro();
    }
}

Note que no construtor da classe você pode passar como parâmetro: o ano, mês, dia, horas, minutos e segundos para iniciar o timer e ainda escolher se deseja contagem regressiva ou progressiva.

No exemplo, o cronometro inicia em 10 horas, 30 minutos e 5 segundos.

:thumbup: [/quote]

neste caso:

ele recebe data/hora do sistema como se fosse um Date data = new Date(); ?

Agradeço a resposta de todos e desculpem a demora para responder, me enrolei no resto do dia e fiquei sem acesso ao pc em casa.

pois é, Calendar cal = Calendar.getInstance(); e Date dat = new Date() pegam a hora do sistema do usuario.

você poderia criar um metodo no lado servidor:

tipo:

public Calendar(ou Date) getHoraAtual(){
return Calendar.getInstance() ou new Date();
}

Vc pode escolher qual usar :slight_smile:

agora entendi, pena que não vou poder testar agora, to envolvido com outra etapa do processo que é bem mais urgente, mas logo mais dou um feedback aqui de como foi implementado.

Valeu mesmo a ajuda :slight_smile:

Consegui implementar o que eu queria, usando Timer e TimerTask, só acho que preciso dar uma melhorada na passagem de parâmetro pro construtor.

Espero que funcione, pois na aplicação que possui o método main eu soh preciso instanciar e chamar o método calculaTempo().

[code]import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

/**
*

  • @author NBruno
    */
    public class TimerAcompanhamento {
    private Timer cronometro = new Timer();

    private Calendar horarioAtual;
    private Calendar horarioLimite;
    private Calendar horarioInicial;

    TimerAcompanhamento(int ano, int mes, int dia, int hora, int minuto, int segundo) {

      horarioInicial = Calendar.getInstance();
      horarioInicial.set(ano, mes, dia, hora, minuto, segundo);
      System.out.println("Hora Inicial: " + horarioInicial.getTime());
      
      horarioLimite = Calendar.getInstance();
      horarioLimite.set(ano, mes, dia, hora, minuto, segundo);
      horarioLimite.add(Calendar.HOUR, 20);
      System.out.println("Hora Limite: " + horarioLimite.getTime());
    

    }

    private String getTempo(long minutos){
    return String.format ("%02d:%02d", (minutos / 60), (minutos % 60));
    }

    public void calculaTempo() {
    TimerTask tarefa = new TimerTask() {

          @Override  
          public void run() {
              horarioAtual = Calendar.getInstance();
              
              if (horarioAtual.getTimeInMillis() < horarioLimite.getTimeInMillis()) {
                  long milisegundoRestante = horarioLimite.getTimeInMillis() - horarioAtual.getTimeInMillis();
                  long minutoRestante = (long)milisegundoRestante/60000;
                  System.out.println("Hora Restante: " + getTempo(minutoRestante));
              } else {
                  long milisegundoExcedido = horarioAtual.getTimeInMillis() - horarioLimite.getTimeInMillis();
                  long minutoExcedido = (long)milisegundoExcedido/60000;
                  System.out.println("Tempo Excedido: " + getTempo(minutoExcedido));
              }
          }  
      };  
      cronometro.scheduleAtFixedRate(tarefa, 0, 1000);  
      this.cronometro = null;
    

    }
    }[/code]

Agradeço a ajuda de todos, pra variar :slight_smile:

1 curtida