Java gui countdown

6.1k views Asked by At

I need to make a GUI where a worker enters a station (a spot on the panel) and stays there for a set amount of seconds, shown in a countdown about the workers head (so, once the workers moves to the spot, the station's label shows 3s -> 2s -> 1s and then the worker leaves, and the label reverts back to "OPEN"). I'm having trouble with making this happen, as I'm not too good with the Timer(s?) that Java has. I tried with something like this:

Timer timer = new Timer(1000, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            //change label text/color, decrement countdown
            panel.repaint();
            Thread.sleep(1000);
        }
    });

But I can't reach the number of seconds to count down from from inside the timer, and I'm not sure how to pass that value to the timer. If someone can help me out, I'd really appreciate it.

2

There are 2 answers

2
Paul Samsotha On

Get rid of the Thread.sleep(). That's what the 1000 in Timer(1000, new ActionListener() does. It sets an interval for each timer event. Every time a timer event is fired, the actionPerformed is called. So you need to determine what needs to happen every "tick", and put that code in the actionPerformed. Maybe something like

Timer timer = new Timer(1000, new ActionListener() {
    private int count = 5;
    @Override
    public void actionPerformed(ActionEvent e) {
        if (count <= 0) {
            label.setText("OPEN");
            ((Timer)e.getSource()).stop();
            count = 5;
        } else {
            label.setText(Integer.toString(count);
            count--;
        }
    }
});

You need to decide when to call timer.start().

0
black panda On

Problem #1: You are calling Thread.sleep() from within the Swing GUI thread. That causes the thread to stop taking input and freeze. Delete that line. It does you no good! While you are at it, delete the repaint call as well.

Now that that's said and done, instead of creating an anonymous instance of ActionListener, you can create an actual class that implements ActionListener and provides a constructor. That constructor can have as an argument the number of seconds you want to start counting down. You can declare that class inside the method you are using, or you can declare it inside the class.

Here's a skeletal example:

public class OuterClass {
   JLabel secondsLabel = ...;
   Timer myTimer;

   private void setupTimer(int numSecondsToCountDown) {
      secondsLabel.setText(Integer.toString(numSecondsToCountDown));
      myTimer = new Timer(1000, new CountdownListener(numSecondsToCountDown));
      myTimer.start();
   }

   // ...
   class CountdownListener implements ActionListener {
      private int secondsCount;

      public CountdownListener(int startingSeconds) { secondsCount = startingSeconds; }

      public void actionPerformed(ActionEvent evt) {
         secondsLabel.setText(Integer.toString(secondsCount);
         secondsCount--;

         if (secondsCount <= 0) { // stop the countdown
            myTimer.stop();
         }
      }
   }
}