I'm having a problem with my countdown timer and am figuring that I'm missing something obvious.

All I'm trying to do here is get my jLabel to countdown from 60 to 0.

ActionListener refreshListener = new ActionListener() {
            int counterLimit = 60;
            public void actionPerformed(ActionEvent e)
            {
                javax.swing.Timer refreshTimer = new javax.swing.Timer(1000, new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    counteLimitr--; 
                    
                    String timerCounter = Integer.toString(counterLimit);
                    countdown.setText(timerCounter);
            
                }
            });
            refreshTimer.start();

        }
    };

Compiles fine, just doesn't countdown.

Recommended Answers

All 19 Replies

Did you add that refreshListener to something? Just glancing at it, what you wrote looks as though it should work fine (except for the syntax error "counteLimitr"), though it won't stop at zero.

commented: You've been very helpful throughout the whole thread, I appreciate it very much +1

That was the problem, initially I had intentions of adding it to a jButton but changed my mind and was just going to run it automatically but forgot to change it to do so.

You are correct about the syntax error, was in a bit of a rush and didn't notice it.

Anyways I went ahead and rewrote it to look like so:

ActionListener refreshListener = new ActionListener() {

            int counterLimit = 60;

            public void actionPerformed(ActionEvent e)
            {
                counterLimit--;
                String timerCounter = Integer.toString(counterLimit);
                countdown.setText(timerCounter);
                System.out.println(counterLimit);
            }
        };

        javax.swing.Timer refreshTimer = new javax.swing.Timer(1000, refreshListener);
        refreshTimer.setInitialDelay(0);
        refreshTimer.start();

It also doesn't stop at 0 like you said, I went ahead and tried to put a for loop in there instead of just counterLimit--; but that automatically makes it count much faster than a second.

Is there an easy way to make it stop at 0? I'm planning on making it reset to 60 once it hits 0.

When your counter gets to zero, stop the timer and reset the counter to 60.

Wouldn't there be a problem with the scope?

ActionListener refreshListener = new ActionListener() {

            int counterLimit = 60;

            public void actionPerformed(ActionEvent e)
            {
                counterLimit--;
                String timerCounter = Integer.toString(counterLimit);
                countdown.setText(timerCounter);
                System.out.println(counterLimit);
            }
        };

        javax.swing.Timer refreshTimer = new javax.swing.Timer(1000, refreshListener);
        refreshTimer.setInitialDelay(0);
        refreshTimer.start();
       
         if ([B][U]counter[/U][/B] == 0) {
            refreshTimer.stop();
            refreshTimer.restart();
        }

Where counter isn't accessible since it is outside of the scope where I defined it?

Well, yes, if you put it outside the listener like that - so don't do that. Place the check and the reset in the actionPerformed() method. You can stop the timer there also.

Doing it that way would mean refreshTimer isn't accessible if I'm doing it correctly

ActionListener refreshListener = new ActionListener() {

            int counter = 60;

            public void actionPerformed(ActionEvent e)
            {
                counterLimit--;
                String timerCounter = Integer.toString(counterLimit);
                countdown.setText(timerCounter + "(s)");
                System.out.println(counterLimit + "(s)");
                
[B]                if (counter == 0) {
                    refreshTimer.stop();
                    refreshTimer.restart();[/B]
                            
                }
            }
            
        };
  
         javax.swing.Timer refreshTimer = new javax.swing.Timer(1000, refreshListener);
        refreshTimer.setInitialDelay(0);
        refreshTimer.start();

I do realize that it hasn't been declared in the actionPerformed, however when declaring it in there instead of outside it then has a problem with 'refreshListener'

I have a feeling I made a dumb mistake though, I appreciate your patience.

It would be a bit cleaner if you just combined them into a small class

class CountdownTimer implements ActionListener {
    int counter = 60;
    javax.swing.Timer refreshTimer;

    public CountdownTimer(){
        refreshTimer = new javax.swing.Timer(1000, this);
    }

    public void actionPerformed(ActionEvent e) {
        counter--;
        System.out.println(counter);
        if (counter==0){
            stop();
            reset();
        }
    }

    public void start(){
        refreshTimer.start();
    }
    public void stop(){
        refreshTimer.stop();
    }
    public void reset(){
        counter = 60;
    }
}

If it is in a separate class then how would I get my jLabel to display it? (my jLabel displaying it is the most important part of it)

I had previously wanted to make it a separate class because it does make it much cleaner, but I didn't know how to go about making my jLabel display it from another class.

If it's an inner class, it can still access your JLabel just fine.

Can you point me in the right direction on what I should search for in google or a tutorial on accessing components from inner classes? As google doesn't seem to give me any good sources.

Knowing this information would help me make my program look much cleaner. I had tried to find out how to access components from inner classes awhile back and I couldn't find any decent sources on how to get it to work.

I had tried something like:

CountdownTimer cdt = new CountdownTimer();
        String timerCounter = Integer.toString(counterLimit);
        countdown.setText(timerCounter);

And it tells me that it cannot find the symbol variable counterLimit

Thanks again

You actually want to set the label's text from within your actionPerformed() method of the timer, so change the System.out.println() to

public void actionPerformed(ActionEvent e) {
        counter--;
        [B]countdown.setText(String.valueOf(counter));[/B]
        if (counter==0){
            stop();
            reset();
        }
    }

But my jLabel countdown is from that other class which would create the same problem just in reverse, wouldn't it?


One class is StatusBar, which contains my jLabel (countdown) and then the new class that was just created, CountdownTimer.

CountdownTimer can just be a private inner class of StatusBar. It's only a helper object to manage your timer count down and doesn't need to be a top-level public class. As an inner class, it has access to everything in StatusBar so setting the label text is no problem.

Edit: You were already effectively using two anonymous inner classes to manage this functionality in your first version. This just combines them and encapsulates the function into one small helper class.

commented: It feels goood to be back, and see that you're still helping out. Maybe I can lighten the load a little again ;) +10

I actually just realized that right before I read your post. My apologies for being confusing about the inner classes, I went ahead and made it a top-level class and tried bringing it in the way I posted above.

Thank you very much for all the help you provided me with. I'm going to test it out and will be back with an update shortly

I'm double posting so that you see there is another post in here (you can merge them once you see it if you'd like)

I'm a bit confused about this, I can't get it to use that if statement that was created. It counts all the way down to 0, but sticks on 0.


I tried: cdt.reset(); after cdt.start(); and it doesn't reset it. So I then tried.


CountdownTimer cdt = new CountdownTimer();
cdt.start();

I tried: cdt.actionPerformed(); but it says it can't be applied.


Sorry for all the questions, I just want to understand this as best I can, so that I don't have to question it later.

How are you wanting to reset it? Is there some action that should prompt the reset or should it just start counting from 60 again? You don't have to stop the timer if you don't want to when zero is reached.

Once it hits 0, I want it to delay for a brief amount of time (2 seconds max) and then restart at 60 and count down again.

Basically what it will be doing is when it hits 0, it will refresh my GUI. I am having some beans load information from a file and that file will be updated every so often. So I want it to update it every minute in case there is new information.

I'd say just let the timer keep running then. You can handle the delay before restart and the reset to 60 easily

class CountdownTimer implements ActionListener {
    final int TOTAL_TIME = 60;
    int counter = TOTAL_TIME;
    javax.swing.Timer refreshTimer;

    public CountdownTimer(){
        refreshTimer = new javax.swing.Timer(1000, this);
    }

    public void actionPerformed(ActionEvent e) {
        counter--;
        if (counter>=0){
            System.out.println(counter);
        }
        if (counter == -2){
            reset();
        }
    }

    public void start(){
        refreshTimer.start();
    }
    public void stop(){
        refreshTimer.stop();
    }
    public void reset(){
        counter = TOTAL_TIME;
    }
}

Thank you for all your help, I have modified it slightly and it works exactly how I was wanting.

Much appreciated :)

-Solved-

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.