Reputation: 1129
I use a Swing.Timer to slow my animation. However, I want to pause my current execution until after the Timer thread completes. How do I do that? The Timer spawns off a new thread that is not responsive to the original. Here is a sample program that demonstrates.
public class TimerFrame extends JFrame
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable() {
@Override
public void run()
{
TimerFrame frame = new TimerFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
TimeListener listener = new TimeListener();
Timer timer = new Timer(1000, listener);
timer.start();
System.out.println("Timer running: " + timer);
while (!timer.isRunning()) {
System.out.println("Timer not running: " + timer);
JOptionPane.showMessageDialog(null, "Quit program?");
Calendar cal = Calendar.getInstance();
System.out.println("main pgm: " + cal.getTimeInMillis());
}
System.exit(0);
}
});
}
}
class TimeListener implements ActionListener
{
static int _counter;
public TimeListener()
{
_counter = 1;
}
@Override
public void actionPerformed(ActionEvent e)
{
if (_counter <= 3) {
String msg = "Timer: Counter = " + _counter + " " + e.getWhen();
JOptionPane.showMessageDialog(null, msg);
System.out.println(msg);
_counter++;
}
else {
Timer timer = (Timer) e.getSource();
timer.stop();
if (timer.isRunning()) {
System.out.println("Timer.aP is still running after a stop request");
}
else {
System.out.println("Timer.aP just stopped timer");
}
}
}
}
Note that the timer continues to run even though actionPerformed stops it. After three OptionPane appearances, the program never quits. I expected that the isRunnable() test would be false when the timer completes. The output is
Timer running: javax.swing.Timer@2eb9b326
Timer: Counter = 1 1606837382597
Timer: Counter = 2 1606837385600
Timer: Counter = 3 1606837386601
Timer.aP just stopped timer
Upvotes: 0
Views: 202
Reputation: 1129
I wrote a few test programs and found a way: Put a flag into the Listener class to true when the timer stops, and a getter to return the state of the flag. The calling program loops until the timeer is completed. Here is the Listener code.
class TimeListener implements ActionListener
{
static int _counter;
boolean _endTimer;
public TimeListener()
{
_counter = 1;
_endTimer = false;
}
boolean isTimerDone()
{
return _endTimer;
}
@Override
public void actionPerformed(ActionEvent e)
{
if (_counter <= 3) {
String msg = "Timer: Counter = " + _counter + " " + e.getWhen();
JOptionPane.showMessageDialog(null, msg);
System.out.println(msg);
_counter++;
}
else {
Timer timer = (Timer) e.getSource();
timer.stop();
_endTimer = true;
}
}
}
In the calling program (the one waiting for the timer to end), use a loop to check until the timer is done:
TimeListener listener = new TimeListener();
Timer timer = new Timer(1000, listener);
timer.start();
// Wait until the timer completes
while (listener.isTimerDone());
// continue code here...
Upvotes: 1