1

I have a problem with a Timer in a chess i'm doing. It's working "fine", except it counts seconds two on two (2:00 > 1:58 > 1:56, etc.. but that's with a 1-second interval, not 2-second interval)

here' the code where i define, start, and end the timer:

private void setTime(){
    totalTime=20;
    whiteSec=0;
    whiteMin=totalTime;
    blackSec=0;
    blackMin=totalTime;
    ActionListener taskPerformer = new ActionListener() {
          public void actionPerformed(ActionEvent evt) {
              if(whiteActive){
                  if(whiteSec>0) whiteSec-=1;
                  else{
                      whiteMin-=1;
                      whiteSec=60;
                  }
                  if(whiteMin==0 && whiteSec==0) endGame();
                  else GUI.setPlayerTime(whiteMin, whiteSec);
              }else{
                  if(blackSec>0) blackSec-=1;
                  else{
                      blackMin-=1;
                      blackSec=60;
                  }
                  if(blackMin==0 && blackSec==0) endGame();
                  else GUI.setPlayerTime(blackMin, blackSec);
              }
          }
      };
    chessTimer = new Timer(1000, taskPerformer);
}

//start

whiteActive = true;
setTime();
wCastling = true;
bCastling = true;
canEnPassant = false;
GUI.setPlayerTime(whiteMin, whiteSec); //this writes the time in some JLabels.
guiRefresh();
activePiece = null;
chessTimer.start();

//end

private void endGame(){
    GUI.endGame(checkMate);  //shows an endgame JOptionPane
    chessTimer.stop();
}

I'd appreciate any help!

Iñaki Guastalli
  • 147
  • 2
  • 13
  • Besides, you'd better do `whiteTime.decrease1Sec();` and encapsulate the minute/second logic inside a class. – ignis Dec 17 '12 at 07:04
  • Have you done debugging on this code to make sure it's not being called twice per second? Maybe your paint refresh only occurs every 2 seconds? – Ryan Amos Dec 17 '12 at 07:06
  • i was planning on doing just that as soon as i can get this working properly :P tried to have everything "at hand" to work with, and then i encapsulate it properly.. i dunno if that's the best call, but i'm relatively new to objects', so i just do my best – Iñaki Guastalli Dec 17 '12 at 07:08
  • Anyway, as popfalushi tells, you cannot expect the timer to work exactly at 1 second intervals (and you have to add processing time). So, you will probably spend 105 seconds (or 95) doing 100 iterations. Do more frequent iterations (perhaps each 100ms) and compare with the system internal time to see how much time has really passed the the current player has become active. – SJuan76 Dec 17 '12 at 07:20
  • I don't really need atomic-clock swiss precision here, just nothing so brute as two seconds in one! – Iñaki Guastalli Dec 17 '12 at 07:23
  • I've checked that after the "stop()", the timer goes on, but on 1 second intervals.. but i don't find any other "start()".. can a single timer be.. started twice? – Iñaki Guastalli Dec 17 '12 at 07:24
  • 1
    Unable to reproduce at 1 Hz, for [example](http://stackoverflow.com/a/2166500/230513); please edit your question to include an [sscce](http://sscce.org/) that exhibits the problem you describe. – trashgod Dec 17 '12 at 07:52
  • 1
    you can call `restart()` on `java.swingx.Timer` to start it again. Im really struggling to see the problem here besides maybe latency in the calls etc an example of yours such as a simple timer that counts down from a given time may shed some more light – David Kroukamp Dec 17 '12 at 10:06

2 Answers2

4

While I do not believe a Timer can be started twice, multiple calls to setTime() would create multiple timers, each of which would independently decrement the fields (until the first is garbage collected, which may or may not happen). If you call the method twice in a row, the two Timer objects would coexist for a while, and it would probably decrement twice per second; calling stop() would stop one of the timers and keep the other around.

As a debugging step (and a good practice overall), check that you don't already have a timer before you create a new one:

/* ... */
if (chessTimer != null) throw new IllegalStateException("setTime already called");
chessTimer = new Timer(1000, taskPerformer);

To fix it, track down the duplicate call, or band-aid over it by replacing the IllegalStateException with chessTimer.stop();.

Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • Multiple instances of `javax.swing.Timer` "perform their waiting using a single, shared thread." – trashgod Dec 17 '12 at 07:45
  • @trashgod They do share the same thread, but each Timer will fire its event separately. SSCCE: http://pastebin.com/0e0vmWBr – Jeff Bowman Dec 17 '12 at 07:57
  • Why not include your sscce in the answer? I don't think this is the cause, but it may give some insight. +1 for `MessageFormat`. I'm guessing a logical error in managing `whiteActive`. – trashgod Dec 17 '12 at 08:22
  • It was in fact a 2do call to setTime().. i found it highly unlikely for that to happen, as i had it called inside a method that was called a single time inside the constructor of a singleton class.. Buuut, unlucky me, i had that same method -the one that called setTime()- as public, and i was calling it from the main class.. all my main class does is create an instance of the singleton class.. .. .. .. ..and call that damn method hahahaha.. i haven't touched the main class in like.. months. Misfortune at it's worst. – Iñaki Guastalli Dec 21 '12 at 01:24
  • @IñakiGuastalli Glad to help you out! Please [accept my answer](http://stackoverflow.com/faq#howtoask) if it solved your problem. Happy holidays! – Jeff Bowman Dec 21 '12 at 01:28
1

from http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html: This class does not offer real-time guarantees: it schedules tasks using the Object.wait(long) method.

popfalushi
  • 1,332
  • 9
  • 15
  • I agree that he should not being doing it this way, but that does not explain why the counter is decreasing by two each time. – SJuan76 Dec 17 '12 at 07:16
  • I edited the question to add the codes where i originally call the function that defines the timer, and when i stop the timer, if it helps in anything – Iñaki Guastalli Dec 17 '12 at 07:37
  • 1
    The question refers to `javax.swing.Timer`, not `java.util.Timer`; see also this [example](http://stackoverflow.com/a/2166500/230513). – trashgod Dec 17 '12 at 07:50