I have a timer with a delay of 5 seconds. I am trying to change the label named lblTimer after a second passes to act as a countdown. I am having issues with it as currently it only works at 5 seconds. Do you have any suggestionsuggestions?
protected void Addition() {
//addition function
final int delay = 5000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
@SuppressWarnings("unused")
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
frame.getContentPane().setBackground(Color.red);
}
};
new Timer(delay, taskPerformer).start();
Random RandomNumber = new Random();
int number1 = RandomNumber.nextInt(12);
int number2 = RandomNumber.nextInt(12);
int number3 = RandomNumber.nextInt(12);
lblAnswer.setText("");
lblFirstNumber.setText(""+ number1);
lblfunction1.setText("+");
lblsecondNumber.setText(""+number2);
lblfunction2.setText("+");
lblthirdnumber.setText(""+number3);
lblequals.setText("=");
answer = number1+number2+number3;
if(delay <= 1000){
lblTimer.setText("1");
}
else if(delay == 2000){
lblTimer.setText("2");
}
else if(delay == 3000){
lblTimer.setText("3");
}
else if(delay == 4000){
lblTimer.setText("4");
}
else if (delay == 5000){
lblTimer.setText("5");
}
}
The answer to your question, that I assume is "why does this not work?", is that at no point do you recheck the elapsed time. The variable delay is always set at 5000, and never updated, also.
The stupid-ass solution:
lblTimer.setText("5");
Thread.sleep(1000)
lblTimer.setText("4");
Thread.sleep(1000)
lblTimer.setText("3");
Thread.sleep(1000)
lblTimer.setText("2");
Thread.sleep(1000)
lblTimer.setText("1");
Thread.sleep(1000)
lblTimer.setText("0");
Don't really do this, unless you need to satisfy your sick fetishes.
The four-liner
The same as above. Don't do this.
for (int i = secondsToWait; i >= 0; i--) {
lblTimer.setText(i + "");
Thread.sleep(1000);
}
The acceptable solution:
Use a Timer to schedule a task to be executed after a given period of time. You can use timers to also fire the same task multiple times at a given interval.
Timer timer = new Timer();
int secondsToWait = 5;
TimerTask task = new TimerTask() {
@Override
public void run() {
secondsToWait--;
lblTimer.setText(secondsToWait + "");
if (secondsToWait == 0) {
timer.cancel();
timer.purge();
}
}
};
lblTimer.setText(secondsToWait + "");
timer.scheduleAtFixedRate(task, 1000, 1000);
The best solution:
Instead of a timer, use a ScheduledExecutorService. This is better because of the way ScheduledExecutorService works with threads as opposed to Timer. Google it.
ScheduledExecutorService exec = Executors.newScheduledThreadPool(1);
int secondsToWait = 5;
Runnable task = new Runnable() {
@Override
public void run() {
secondsToWait--;
lblTimer.setText(secondsToWait + "");
if (secondsToWait == 0) {
exec.shutdown();
}
}
};
lblTimer.setText(secondsToWait + "");
exec.scheduleAtFixedRate(task, 1, 1, TimeUnit.SECONDS);
EDIT: As Stefan pointed out, for swing GUI applications a swing Timer would be the best pick.