Timer Countdown - Code Syntax
Hello! I'm currently working on a program in my spare time for fun. In the program you can press a button, in which it will start a countdown. I've come up with a really sloppy way to do this and I was hoping someone with more experience could point me to a more robust and clean way to go about it. I'm trying to do it in the format minutes:seconds and if you look at my code below, you can see why it's not working properly (digits below 10 show up at 9 instead of 09). Thank you for any help in advanced!
Code Java:
[CODE]
if(clickedOn == button1){
button1.setText("6:00");
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask(){
int i = 59;
int j = 360;
int k = 5;
public void run(){
if(i == 0){
i = 59;
k--;
}
progressBar.setValue(j--);
button1.setText(k+":"+i--);
if(k <= 0 && i <= 0){
timer.cancel();
progressBar.setValue(0);
button1.setText("0:00");
}
if (i < 0)
timer.cancel();
}
}, 0, 1000);
}[/CODE]
I searched on google and found some similar ideas, but my no understanding of Timers caused me to have trouble.
edit: I also want it so when you press the button, it resets the timer back. Currently if I press the button multiple times, it starts a new timer and bugs out the display text (which is trying to display all the timers running).
Re: Timer Countdown - Code Syntax
Quote:
digits below 10 show up at 9 instead of 09).
Build the value to be displayed in a String and if the value is < 10, concatenate a "0" in front of it.
An easy way is to use the ternary operator that is like an inline method.
Re: Timer Countdown - Code Syntax
My best advice for the moment is to either
A.) Scrap your java.util.Timer implementation and instead use a javax.swing.Timer implementation.
B.) Combine current implementation with SwingUtilities.invokeLater() so that the work is done on the EDT.
javax.swing.Timer already processes its work on the EDT, so you don't need to do anything special.
The reason for this is because inside your timer, you are altering GUI components. If you alter components which are running on the EDT on a task which is running separately, then it can produce irregular results.
Keys*: EDT = Event Dispatch Thread, this is where gui components are ran.
Re: Timer Countdown - Code Syntax
So I took your advice and scrapped my timer and implemented a javax.swing.Timer. However, I am having an issue with restarting it still. What I want to do is, the user presses a button and the timer starts. If the user presses the button again, before it has gotten to 0, I want it to restart the timer back to 5 minutes. What is happening now is, when you press the button again, the timer speed increases for some reason. So if you click it like 100 times, it will countdown 100 times faster. Here is my code, any help is grateful:
Code Java:
public void seven(){
bBlueBuffBar.setString("BLUE Golem - 5:00");
bouncer++;
timer = new Timer(1000, new ActionListener(){
public void actionPerformed(ActionEvent event){
if(bGolemi == 0){
bGolemi = 59;
bGolemk--;
}
sevenB = ""+bGolemi--;
bBlueBuffBar.setValue(bGolemj--);
bBlueBuffBar.setString("BLUE Golem - "+bGolemk+":"+sevenB);
if(bGolemk <= 0 && bGolemi <= 0){
timer.stop();
bBlueBuffBar.setValue(0);
bBlueBuffBar.setString("BLUE Golem - 0:00");;
}
if (bGolemi < 0){
timer.stop();
}
}
});
if(timer.isRunning()){
timer.stop();
bGolemi = 59;
bGolemj = 300;
bGolemk = 4;
timer.start();
}
else{
bGolemi = 59;
bGolemj = 300;
bGolemk = 4;
timer.start();
}
}
timer is a global variable, as well as bGolemi, bGolemj, and bGolemk.
Re: Timer Countdown - Code Syntax
Can you make a small, complete program that compiles, executes and shows the problem?
Re: Timer Countdown - Code Syntax
Try this, let me know if it won't let you download. https://www.dropbox.com/s/af58zy14nc...imerBroken.jar
The program has a key listener, so when you press '7', it should start the timer. Anytime you press 7 multiple times, it gets all messed up like described before.
Re: Timer Countdown - Code Syntax
Can you post the small, complete program for testing here on the forum?
Re: Timer Countdown - Code Syntax
Code Java:
import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.awt.event.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Random;
import java.util.TimerTask;
//import java.util.Timer;
import java.lang.ClassLoader;
import java.net.URL;
import javax.swing.*;
import javax.swing.Timer;
public class Simulator extends JFrame implements MouseListener{
int posX=0,posY=0;
//ImageIcon bBlueBuffIcon = new ImageIcon("Res/images/bgolem.png");
ImageIcon bBlueBuffIcon = new ImageIcon(getClass().getResource("/Res/images/bgolem.png"));
ImageIcon pBlueBuffIcon = new ImageIcon(getClass().getResource("/Res/images/pgolem.png"));
ImageIcon bRedBuffIcon = new ImageIcon(getClass().getResource("Res/images/bred.png"));
ImageIcon pRedBuffIcon = new ImageIcon(getClass().getResource("Res/images/pred.png"));
ImageIcon baronIcon = new ImageIcon(getClass().getResource("Res/images/baron.png"));
ImageIcon dragonBuffIcon = new ImageIcon(getClass().getResource("Res/images/dragon.png"));
private JButton bBlueBuff = new JButton(bBlueBuffIcon);
private JButton pBlueBuff = new JButton(pBlueBuffIcon);
private JButton bRedBuff = new JButton(bRedBuffIcon);
private JButton pRedBuff = new JButton(pRedBuffIcon);
private JButton dragon = new JButton(dragonBuffIcon);
private JButton baron = new JButton(baronIcon);
private JButton reset = new JButton("Reset");
private JButton resize = new JButton("Resize");
//ActionListener listener = new ActionListener();
//final Timer dragonTimer = new Timer(1000, listener);
private JPanel p1 = new JPanel();
private JPanel p2 = new JPanel();
private JPanel p3 = new JPanel();
private JPanel p4 = new JPanel();
private JPanel p5 = new JPanel();
private JPanel p6 = new JPanel();
private JPanel p0 = new JPanel();
private static JProgressBar bBlueBuffBar = new JProgressBar();
private JProgressBar pBlueBuffBar = new JProgressBar();
private JProgressBar bRedBuffBar = new JProgressBar();
private JProgressBar pRedBuffBar = new JProgressBar();
private JProgressBar baronBar = new JProgressBar();
private JProgressBar dragonBar = new JProgressBar();
//private JButton BBlueBuff = new JButton();
//private JButton BBlueBuff = new JButton();
public final static int ONE_SECOND = 1000;
public int toggle = 0;
public String sevenB = "";
public String eightB = "";
public String nineB = "";
public String tenB = "";
public String elevenB = "";
public String twelveB = "";
public int bouncer = 0;
public int bGolemi = 10;
public int bGolemj = 300;
public int bGolemk = 0;
//private static Action EnterAction = null;
//private static Action EnterAction2 = null;
private Timer timer;
public static void main(String[] args) {
Simulator gui = new Simulator();
gui.setVisible(true);
}
public Simulator() {
Font font = new Font("Arial", Font.PLAIN, 20);
GridLayout experimentLayout = new GridLayout(1,1);
GridLayout experimentLayout2 = new GridLayout(3,2);
this.setLayout(experimentLayout);
this.setUndecorated(true);
this.setDefaultLookAndFeelDecorated(false);
//this.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
this.setSize(250,50);
this.setLocation(50,50);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
//this.setResizable(false);
this.setAlwaysOnTop(true);
this.setTitle("League Timers");
this.add(p0);
//this.setIconImage();
p0.setLayout(experimentLayout2);
//p0.setBorder(BorderFactory.createRaisedSoftBevelBorder());
Container cont = getContentPane();
((JComponent) cont).setBorder(BorderFactory.createLineBorder(Color.black, 3));
//((JComponent) cont).setBackground(Color.black);
this.addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
posX=e.getX();
posY=e.getY();
}
});
this.addMouseMotionListener(new MouseAdapter()
{
public void mouseDragged(MouseEvent evt)
{
//sets frame position when mouse dragged
setLocation (evt.getXOnScreen()-posX,evt.getYOnScreen()-posY);
}
});
p1.setLayout(experimentLayout);
p1.setVisible(true);
p1.setFocusable(false);
//p2.setLocation(0,0);
p2.setLayout(experimentLayout);
p2.setVisible(true);
p2.setFocusable(false);
//p3.setLocation(0,0);
p3.setLayout(experimentLayout);
p3.setVisible(true);
p3.setFocusable(false);
//p4.setLocation(0,0);
p4.setLayout(experimentLayout);
p4.setVisible(true);
p4.setFocusable(false);
//p5.setLocation(0,0);
p5.setLayout(experimentLayout);
p5.setVisible(true);
//p5.setFocusable(false);
//p6.setLocation(0,0);
p6.setLayout(experimentLayout);
p6.setVisible(true);
//p6.setFocusable(false);
p0.add(p1);
p0.add(p2);
p0.add(p3);
p0.add(p4);
p0.add(p5);
p0.add(p6);
p1.add(bBlueBuffBar);
p2.add(bRedBuffBar);
p3.add(pBlueBuffBar);
p4.add(pRedBuffBar);
p5.add(dragonBar);
p6.add(baronBar);
//p0.add(reset);
Color customColor = new Color(115,0,255);
Color customColor2 = new Color(37,204,37);
bBlueBuffBar.setBackground(Color.white);
bBlueBuffBar.setForeground(Color.blue);
//bBlueBuffBar.selectionBackground(Color.black);
bBlueBuffBar.setStringPainted(true);
bBlueBuffBar.setString("BLUE Golem - 5:00");
bBlueBuffBar.setMaximum(300);
bBlueBuffBar.setBorder(BorderFactory.createLineBorder(Color.black));
pBlueBuffBar.setBackground(Color.white);
pBlueBuffBar.setForeground(customColor);
pBlueBuffBar.setStringPainted(true);
pBlueBuffBar.setString("PURPLE Golem - 5:00");
pBlueBuffBar.setMaximum(300);
pBlueBuffBar.setBorder(BorderFactory.createLineBorder(Color.black));
bRedBuffBar.setBackground(Color.white);
bRedBuffBar.setForeground(Color.blue);
bRedBuffBar.setStringPainted(true);
bRedBuffBar.setString("BLUE Lizard - 5:00");
bRedBuffBar.setMaximum(300);
bRedBuffBar.setBorder(BorderFactory.createLineBorder(Color.black));
pRedBuffBar.setBackground(Color.white);
pRedBuffBar.setForeground(customColor);
pRedBuffBar.setStringPainted(true);
pRedBuffBar.setString("PURPLE Lizard - 5:00");
pRedBuffBar.setMaximum(300);
pRedBuffBar.setBorder(BorderFactory.createLineBorder(Color.black));
baronBar.setBackground(Color.white);
baronBar.setForeground(customColor2);
baronBar.setStringPainted(true);
baronBar.setString("Baron - 7:00");
baronBar.setMaximum(420);
baronBar.setBorder(BorderFactory.createLineBorder(Color.black));
dragonBar.setBackground(Color.white);
dragonBar.setForeground(customColor2);
dragonBar.setStringPainted(true);
dragonBar.setString("Dragon - 6:00");
dragonBar.setMaximum(360);
dragonBar.setBorder(BorderFactory.createLineBorder(Color.black));
this.addKeyListener(new KeyListener(){
@Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
if(arg0.getKeyChar() == '7'){
seven();
}
if(arg0.getKeyChar() == '8'){
//eight();
}
if(arg0.getKeyChar() == '9'){
//nine();
}
if(arg0.getKeyChar() == '0'){
//ten();
}
if(arg0.getKeyChar() == '-'){
//eleven();
}
if(arg0.getKeyChar() == '='){
//twelve();
}
}
@Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
});
this.setFocusable(true);
//this.requestFocus(true);
}
public void seven(){
bBlueBuffBar.setString("BLUE Golem - 5:00");
bouncer++;
timer = new Timer(1000, new ActionListener(){
public void actionPerformed(ActionEvent event){
// if(bouncer == 2){
// timer.stop();
// bGolemi = 59;
// bGolemj = 300;
// bGolemk = 4;
// bouncer = 0;
// timer.restart();
// }
if(bGolemi == 0){
bGolemi = 59;
bGolemk--;
}
sevenB = ""+bGolemi--;
bBlueBuffBar.setValue(bGolemj--);
bBlueBuffBar.setString("BLUE Golem - "+bGolemk+":"+sevenB);
if(bGolemk <= 0 && bGolemi <= 0){
timer.stop();
bBlueBuffBar.setValue(0);
bBlueBuffBar.setString("BLUE Golem - 0:00");;
}
if (bGolemi < 0){
timer.stop();
}
}
});
if(timer.isRunning()){
timer.stop();
bGolemi = 59;
bGolemj = 300;
bGolemk = 4;
timer.start();
}
else{
bGolemi = 59;
bGolemj = 300;
bGolemk = 4;
timer.start();
}
}
/*
public void eight(){
bRedBuffBar.setString("BLUE Lizard - 5:00");
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask(){
int i = 59;
int j = 300;
int k = 4;
public void run(){
if(i == 0){
i = 59;
k--;
}
bRedBuffBar.setValue(j--);
//bBlueBuff.setText(k+":"+i--);
bRedBuffBar.setString("BLUE Lizard - "+k+":"+i--);
if(k <= 0 && i <= 0){
timer.cancel();
bRedBuffBar.setValue(0);
bRedBuffBar.setString("BLUE Lizard - 0:00");;
}
if (i < 0)
timer.cancel();
}
}, 0, 1000);
}
public void nine(){
pBlueBuffBar.setString("PURPLE Golem - 5:00");
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask(){
int i = 59;
int j = 300;
int k = 4;
public void run(){
if(i == 0){
i = 59;
k--;
}
pBlueBuffBar.setValue(j--);
//bBlueBuff.setText(k+":"+i--);
pBlueBuffBar.setString("PURPLE Golem - "+k+":"+i--);
if(k <= 0 && i <= 0){
timer.cancel();
pBlueBuffBar.setValue(0);
pBlueBuffBar.setString("PURPLE Golem - 0:00");;
}
if (i < 0)
timer.cancel();
}
}, 0, 1000);
}
public void ten(){
pRedBuffBar.setString("PURPLE Lizard - 5:00");
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask(){
int i = 59;
int j = 300;
int k = 4;
public void run(){
if(i == 0){
i = 59;
k--;
}
pRedBuffBar.setValue(j--);
//bBlueBuff.setText(k+":"+i--);
pRedBuffBar.setString("PURPLE Lizard - "+k+":"+i--);
if(k <= 0 && i <= 0){
timer.cancel();
pRedBuffBar.setValue(0);
pRedBuffBar.setString("PURPLE Lizard - 0:00");;
}
if (i < 0)
timer.cancel();
}
}, 0, 1000);
}
public void eleven(){
bouncer++;
if(bouncer == 2){
dragonTimer.cancel();
bouncer = 0;
}
dragonBar.setString("Dragon - 6:00");
dragonTimer.scheduleAtFixedRate(new TimerTask(){
int i = 59;
int j = 360;
int k = 5;
public void run(){
if(i == 0){
i = 59;
k--;
}
dragonBar.setValue(j--);
//bBlueBuff.setText(k+":"+i--);
dragonBar.setString("Dragon - "+k+":"+i--);
StringSelection pst = new StringSelection("Dragon Spawns in "+k+":"+i);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(pst, null);
if(k == 0 && i == 30){
//dragonBar.
}
if(k <= 0 && i <= 0){
dragonTimer.cancel();
dragonBar.setValue(0);
dragonBar.setString("Dragon - 0:00");
}
//if (i < 0)
//dragonTimer.cancel();
}
}, 0, 1000);
}
public void twelve(){
baronBar.setString("Baron - 7:00");
final Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask(){
int i = 59;
int j = 420;
int k = 6;
public void run(){
if(i == 0){
i = 59;
k--;
}
baronBar.setValue(j--);
//bBlueBuff.setText(k+":"+i--);
baronBar.setString("Baron - "+k+":"+i--);
if(k <= 0 && i <= 0){
timer.cancel();
baronBar.setValue(0);
baronBar.setString("Baron - 0:00");;
}
if (i < 0)
timer.cancel();
}
}, 0, 1000);
}*/
@Override
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
Re: Timer Countdown - Code Syntax
Not a SMALL program and it has too many dependencies: images that make it hard to test. Why these images for the test ????
What do you need to do to see the problem?
I get a small rectangle with 3 rows, two columns with upper left square blue after I press "7" a couple of times.
There is a number that is "counting down". I press "7" and the counter restarts. Pressed it several times and restarted each time.
Re: Timer Countdown - Code Syntax
I don't use the images anymore (or buttons for that matter). If you run it, it's pretty simple and if you use the debug tool you can step through the code (which I have done). The problem is I must be using the swing timer incorrectly. When i use the .stop(), it just stops the timer, but when I use start() it like creates a new instance of the timer. Because they use the same variables, I think pressing the listenerkey more than once causes it to run multiple threads of the actionlistener for the timer, which causes the time to get messed up. I don't know how to fix it.
Re: Timer Countdown - Code Syntax
Sorry, I don't have an interactive debugger.
The code executes for me. Can you explain what the problem is and how it can be observed?
Re: Timer Countdown - Code Syntax
Quote:
Originally Posted by
Norm
What do you need to do to see the problem?
I get a small rectangle with 3 rows, two columns with upper left square blue after I press "7" a couple of times.
There is a number that is "counting down". I press "7" and the counter restarts. Pressed it several times and restarted each time.
When I press 7 multiple times, it resets the count to 5:00, but it starts to count down faster. It might not be noticeable with only a few presses, but if you press 7 like 10+ times, it starts counting insanely fast and will start counting negative numbers (which it should stop at 0). I don't know, maybe the issue is only with my computer?
Re: Timer Countdown - Code Syntax
Sounds like there is more than one timer running. Each is updating the count down.
Re: Timer Countdown - Code Syntax
Yeah, but I thought that using the Timer.Stop() would kill the first timer, but I don't think it does. This is where I am confused. My guess is that it just stops it (not killing it), so when the button is pressed again, it starts a new timer but the old one is started again too. I guess my question overall is - how do I make a simple countdown timer to count down from 5 minutes? if the button is pressed again, I want it to just reset to 5 and start counting down again. At 0 it just stops until the button is pressed again.
I thought resetting bGolemi, bGolemj, and bGolemk would fix the issue, but that doesn't seem to affect what is happening.
Re: Timer Countdown - Code Syntax
Try debugging the code by adding println statements to print out the value of the timer variable.
Print it out when it is created and print it out in the actionPerformed() method. The toString() method returns a unique id for each object so you can see the id of the object when it is created and when it calls the actionPerformed() method.
The print out will show you what is happening.
Also print out the Event object passed to actionPerformed().
Re: Timer Countdown - Code Syntax
Thanks Norm for all your help. I'll try printing it out and let you know what I find.
Re: Timer Countdown - Code Syntax
Looks like from printing it all out, it is skipping my if(timer.isRunning()){ statement. So it is just always running the else statement and doing timer.start(). I'll see if I can fix this.
Re: Timer Countdown - Code Syntax
Here is one of my print outs:
Quote:
1timer=javax.swing.Timer@da90c
Do understand what the value after the @ signifies and what it can be used for?
It it the hashcode for the object. Each object has a unique value for its hashcode.
You can then look at the various print outs of the value of the timer object and see which ones refer to the same object and which ones refer to a different object.
How many different values do you see for the timer object?
also notice the leading "1" in the print out. Other print outs will have different numbers on them so I can match the print out with the println() that made it.
Code :
System.out.println("1timer="+timer);
....
System.out.println("2timer="+timer);
Re: Timer Countdown - Code Syntax
Everytime I press the keylistener '7', it gives me a different hashcode.
Re: Timer Countdown - Code Syntax
Quote:
it gives me a different hashcode.
The new statement creates a new object.
Re: Timer Countdown - Code Syntax
Whelp, what a pain in the ass, but I fixed it. Thanks for the help. I had to create a new actionlistener and make my timer global and implement that actionlistener. That way it wasnt making a new one each time (so I pretty much did what you suggested). Thanks again.
Re: Timer Countdown - Code Syntax
Code java:
if(timer.isRunning()){
timer.stop();
bGolemi = 59;
bGolemj = 300;
bGolemk = 4;
timer.start();
}
That condition will never be true as you don't start the timer anywhere before this condition is evaluated.
In that case, it will always enter the ELSE clause, and start a timer. The next time you press 7, a new Timer object is created and you again launch another conflicting thread.
I personally believe the reason for this erratic behavior is down to how the event part of Timers are executed on their own thread, separate to the waiting they do together (as said in the doc: Timer (Java Platform SE 7 ))
Whatever is causing it though, you should build the Timer object during an initialisation period and reference that timer in the method, manipulating it with start(), stop() and restart().
Re: Timer Countdown - Code Syntax
Quote:
Originally Posted by
newbie
Code java:
if(timer.isRunning()){
timer.stop();
bGolemi = 59;
bGolemj = 300;
bGolemk = 4;
timer.start();
}
That condition will never be true as you don't start the timer anywhere before this condition is evaluated.
In that case, it will always enter the ELSE clause, and start a timer. The next time you press 7, a new Timer object is created and you again launch another conflicting thread.
I personally believe the reason for this erratic behavior is down to how the event part of Timers are executed on their own thread, separate to the waiting they do together (as said in the doc:
Timer (Java Platform SE 7 ))
Whatever is causing it though, you should build the Timer object during an initialisation period and reference that timer in the method, manipulating it with start(), stop() and restart().
Yeah, that was part of the problem too. I just completely redid it. Here is the code in case someone else is trying to do timers.
Code Java:
//Create my timer
private Timer timer;
public Simulator() {
bGolemTimerLoop timer1 = new bGolemTimerLoop();
timer = new Timer(1000, timer1);
}
public void seven(){
if(timer.isRunning() == true){
timer.stop();
bGolemi = 59;
bGolemj = 300;
bGolemk = 4;
timer.restart();
}
if(timer.isRunning() == false){
bGolemi = 59;
bGolemj = 300;
bGolemk = 4;
timer.start();
}
}
public class bGolemTimerLoop implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
bBlueBuffBar.setString("BLUE Golem - 5:00");
if(bGolemi == 0){
bGolemi = 59;
bGolemk--;
}
sevenB = ""+bGolemi--;
bBlueBuffBar.setValue(bGolemj--);
bBlueBuffBar.setString("BLUE Golem - "+bGolemk+":"+sevenB);
if(bGolemk <= 0 && bGolemi <= 0){
timer.stop();
bBlueBuffBar.setValue(0);
bBlueBuffBar.setString("BLUE Golem - 0:00");;
}
if (bGolemi < 0){
timer.stop();
}
}
}