如何在执行代码之前等待计时器停止?

问题描述:

我有一个用于扩展动画的JPanel的类中的Timer,并且ActionListener侦听它并使actionPerformed运行,它会在需要时重绘并停止计时器。但启动定时器animatePanel的方法会在定时器运行时继续执行,这是我不想要的。我希望它等到定时器停止返回。如何在执行代码之前等待计时器停止?

定时器是在类的构造函数初始化这样的:

timer = new Timer(5, taskPerformer); 

这是它做什么。我有话通话animatePanel():

private ActionListener taskPerformer = new ActionListener() { 
    public void actionPerformed(ActionEvent evt) { 
     ... 
     if (some conditions){ 
      ... 
      timer.stop(); 
      ... 
      return; 
     } 

     ... 
    } 
}; 

private void animatePanel() { 
    ... 
    timer.start(); 
    System.out.println("Timer stopped."); //always executes before the timer has stopped :(
    //then returns and lets the rest of my program run while the timer is still going, which is BAD 
} 

定时器工作正常,只是在某些情况下,animatePanel()也将很快恢复,让我的程序运行的剩余部分,造成的问题。

+0

你能否介绍计时器变量的声明? – 2013-04-22 01:56:07

+0

为了更快得到更好的帮助,请发布[SSCCE](http://sscce.org/)。 – 2013-04-22 01:56:27

+0

如果你从EDT的环境中启动计时器,那么这将炸毁在你的脸上,只是说... – MadProgrammer 2013-04-22 01:57:22

你不能在事件分派线程的上下文中做到这一点,这样做会让你的应用程序挂起!

定时器必须在单独的Thread中启动。这可以让您利用线程监视API。

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class WaitForTimer { 

    public static void main(String[] args) { 
     new WaitForTimer(); 
    } 

    public WaitForTimer() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public static class TestPane extends JPanel { 

     protected static final Object WAIT_FOR = new Object(); 
     private Timer timer; 
     private int tickCount = 0; 
     private JLabel ticks; 
     private JButton start; 

     public TestPane() { 
      timer = new Timer(250, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        tickCount++; 
        if (tickCount > 10) { 
         tickCount = 0; 
         timer.stop(); 
         synchronized (WAIT_FOR) { 
          WAIT_FOR.notifyAll(); 
         } 
         start.setEnabled(true); 
        } 
        ticks.setText(String.valueOf(tickCount)); 
       } 
      }); 
      timer.setRepeats(true); 
      timer.setCoalesce(true); 

      ticks = new JLabel("..."); 
      start = new JButton("Start"); 

      setLayout(new GridBagLayout()); 
      GridBagConstraints gbc = new GridBagConstraints(); 
      gbc.gridwidth = GridBagConstraints.REMAINDER; 
      add(ticks, gbc); 
      add(start, gbc); 

      start.addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        start.setEnabled(false); 
        new Thread(new Runnable() { 
         @Override 
         public void run() { 
          System.out.println("Starting timer..."); 
          timer.start(); 
          synchronized (WAIT_FOR) { 
           try { 
            WAIT_FOR.wait(); 
           } catch (InterruptedException ex) { 
           } 
          } 
          System.out.println("Timer finished..."); 
         } 
        }).start(); 
       } 
      }); 

     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 
    } 
}