6 Replies - 2862 Views - Last Post: 11 May 2010 - 06:48 AM Rate Topic: -----

#1 namkcuR  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 7
  • Joined: 27-October 09

How to make a program wait for a Timer to stop before continuing

Posted 10 May 2010 - 03:25 PM

I am working on a writing a board game in java. As part of this game, a token traverses a board. I've written code, using a Timer object, to advance the token one board space each half second until it reaches its destination. Depending on the space the token lands on, there sometimes will be an JOptionPane window that will pop up to take user input. The problem is that the JOptionPane window pops up before the token has actually reached the space.

Here's two sections of code:

(other stuff)
moveToken(i,currentPosition)  
(other stuff)
int response = JOptionPane.showOptionDialog(null,"",name,JOptionPane.YES_NO_OPTION,JOptionPane.PLAIN_MESSAGE,null,choices,choices[0]);



public void moveToken(int start, int newCurrentPosition)
{
	i = start;
	currentPosition = newCurrentPosition;

        /*i and currentPosition have initialized globally - because they're 
going to be used inside an actionListener - which means they have to be 
either 'final' or 'private static', and since the value of one of them is going to be 
changed, I made them private static, but java doesn't let you initialize private 
static variables inside of a method, as far as I can tell.*/

	final Timer tokenTimer = new Timer(500,new ActionListener()
	{
		public void actionPerformed(ActionEvent e)
		{
					
			
		}
	});

/*The reason for the initial empty actionListener, is that I 
want the actual actionListener to invoke the Timer's own 
stop() method, and if I do that in actionListener that's passed 
to the Timer's constructor, it doesn't compile, because it would 
be looking to call the stop method of an object that, of 
course, hasn't been initialized yet.*/

	tokenTimer.addActionListener(new ActionListener()
	{
		public void actionPerformed(ActionEvent e)
		{
			spaces[i].eraseToken()
			spaces[i+1].setToken(new ImageIcon("images/token.png"));
			i++;
			if(i == currentPosition)
				tokenTimer.stop();
		}
	});

	tokenTimer.start();
}



So, every half second, the timer takes the token off space i, adds it to space i+1, increments i by 1, and then checks to see if i is equal to the currentPosition, and if it is, the timer is stopped.

Just for clarity - the spaces array is of type JImagePanel, a custom class I wrote(starting with some help from google and then adding onto it myself) that extends JPanel.

So, all of that in mind, what happens is that the Timer is started in the moveToken method, and the method returns control to the calling method - part of which is the first section of code I posted - and the calling method continues on before the Timer has stopped, causing the JOptionPane to pop up before the token has reached its destination space.

How can I make the calling method wait until the Timer is stopped before continuing, or make the moveToken method wait until the Timer is stopped before returning control to the calling method? I tried adding the following to the end of the moveToken method:

while(tokenTimer.isRunning())
{}



I thought the while loop would run while the Timer ran, and then once the Timer stopped, the loop would stop, and then control would be returned to the calling method. It didn't work; the program just froze.

My gut instinct here is that my solution may lie in Threads - that the reason my while loop solution didn't work is because there's only one thread running, and the Timer never gets to its stop() method while the while loop is running, thus causing an infinite loop. But that's a guess on my part - I could be wrong.

Anyone have any suggestions for me?

This post has been edited by namkcuR: 10 May 2010 - 03:26 PM


Is This A Good Question/Topic? 1
  • +

Replies To: How to make a program wait for a Timer to stop before continuing

#2 macosxnerd101  Icon User is online

  • Self-Trained Economist
  • member icon




Reputation: 10397
  • View blog
  • Posts: 38,473
  • Joined: 27-December 08

Re: How to make a program wait for a Timer to stop before continuing

Posted 10 May 2010 - 06:00 PM

If you want the Timer to execute this Action every half a second, stopping it probably isn't the way to go. Maybe a better design would be to have the addToken() (or similar) method for your Space class return a boolean based on whether or not it is supposed to display a JOptionPane window. If it returns true, invoke a method on that space to display the window within the paint() method (I'm assuming you are using paint() or paintComponent() in this program to update the displays). This way, the Token will have graphically moved to the new space before the JOptionPane is displayed.
Was This Post Helpful? 0
  • +
  • -

#3 Ember  Icon User is offline

  • D.I.C Head

Reputation: 70
  • View blog
  • Posts: 160
  • Joined: 24-April 10

Re: How to make a program wait for a Timer to stop before continuing

Posted 10 May 2010 - 06:17 PM

Can we see the code for the Timer Object? If you are using the Java.Util timer, you are doing it wrong.

The Java.Util Timer is for Thread Scheduling and probably shouldn't be used for waiting like this.

Also, I have never heard of an array of JPanels for drawing that much stuff. If they are single images, you could easily use JLabels in a JPanel, or just draw all the stuff in one JPanel.

How you set up your objects aside, you could have a method in the overall class called sleep, it would look something like this:

  public  void sleep(long milliseconds) {
    Date d ;
    long start, now ;
    d = new Date() ;
    start = d.getTime() ;
    do { d = new Date() ; now = d.getTime() ; }
    while ( (now - start) < milliseconds ) ;
  }



The code is pretty self-explanatory. It creates a new date object which constantly updates. It takes the now and subtracts it from the start and then checks to see if it is greater than the milliseconds you input. It worked like a charm for me, because it halts the program in a blank while loop for that alloted amount of time. You can also edit it a little and add a boolean flag that will keep the while loop going continuously if there is a JOptionPane open.

If you want to know more about the Date API: http://java.sun.com/.../util/Date.html

The constructor I used checks the time to the nearest millisecond, hence why my method works above :)

This post has been edited by Ember: 10 May 2010 - 06:20 PM

Was This Post Helpful? 0
  • +
  • -

#4 macosxnerd101  Icon User is online

  • Self-Trained Economist
  • member icon




Reputation: 10397
  • View blog
  • Posts: 38,473
  • Joined: 27-December 08

Re: How to make a program wait for a Timer to stop before continuing

Posted 10 May 2010 - 06:24 PM

@Ember: The OP is actually using Swing Timer which piggy-backs off of the EventDispatchThread, not Util Timer, as he is tying it to an ActionListener.

Your thinking is on the right track, but a comparable sleep() method is defined in the Thread class. The whole point of using Swing Timer is to get around scheduling yourself, as you are trying to do, without resorting to Threading (as Swing isn't Thread-safe).
Was This Post Helpful? 0
  • +
  • -

#5 Dogstopper  Icon User is offline

  • The Ninjaducky
  • member icon



Reputation: 2870
  • View blog
  • Posts: 11,023
  • Joined: 15-July 08

Re: How to make a program wait for a Timer to stop before continuing

Posted 10 May 2010 - 06:38 PM

I think ember is making it too complex...
(other stuff)
moveToken(i,currentPosition)  
(other stuff)
int response = JOptionPane.showOptionDialog(null,"",name,JOptionPane.YES_NO_OPTION,JOptionPane.PLAIN_MESSAGE,null,choices,choices[0]);


Quote

The problem is that the JOptionPane window pops up before the token has actually reached the space.


You move the token, but it does not seem to me that you are updating the screen between the events. One thing you could do is call repaint() somewhere in there. What you can do is something like this:
(other stuff)
moveToken(i,currentPosition);
repaint(); // Repaint the screen
timer.stop(); // Stop the game loop temporarily
(other stuff)
int response = JOptionPane.showOptionDialog(null,"",name,JOptionPane.YES_NO_OPTION,JOptionPane.PLAIN_MESSAGE,null,choices,choices[0]);
timer.start(); // Start the loop again.



That might be avoiding the point, but it is a heck of a lot easier than scheduling.
Was This Post Helpful? 0
  • +
  • -

#6 Ember  Icon User is offline

  • D.I.C Head

Reputation: 70
  • View blog
  • Posts: 160
  • Joined: 24-April 10

Re: How to make a program wait for a Timer to stop before continuing

Posted 10 May 2010 - 06:40 PM

View Postmacosxnerd101, on 10 May 2010 - 05:24 PM, said:

@Ember: The OP is actually using Swing Timer which piggy-backs off of the EventDispatchThread, not Util Timer, as he is tying it to an ActionListener.

Your thinking is on the right track, but a comparable sleep() method is defined in the Thread class. The whole point of using Swing Timer is to get around scheduling yourself, as you are trying to do, without resorting to Threading (as Swing isn't Thread-safe).

Ohhh, I see that now. Should have realized that when the constructor for Timer had no arguments that matched any parameters defined in the Timer class in Java.Util.
Was This Post Helpful? 0
  • +
  • -

#7 Luckless  Icon User is offline

  • </luck>
  • member icon

Reputation: 292
  • View blog
  • Posts: 1,146
  • Joined: 31-August 09

Re: How to make a program wait for a Timer to stop before continuing

Posted 11 May 2010 - 06:48 AM

Btw, thanks for presenting your problem in a clear manner, it is a huge help to us and we wish it was done this way more often :bigsmile:
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1