2010-10-04 45 views
25

我試圖停止ActionListener內部的計時器。以下是我想要做的事情的代碼。當我在actionPerformed方法內部滿足一定的條件時,我會停止創建的定時器。 timer.stop()不起作用,編譯器不會讓我這樣做。停止動作偵聽器中的擺動計時器

任何幫助。建議,建議會非常有幫助。

public class ToggleAnnotationsAction extends IdentifiedMultiAction { 
    //This status indicates if the Toggle action has been completed 

/** 
* Defines the toggling direction of a <code>ToggleAnnotationAction</code> instance. 
*/ 
public static enum Direction {FORWARD, BACKWARD}; 
private Direction myDir; 

/** 
* Create an action with the direction presets given by the provided <code>Enum</code>. 
* 
* @param dir An <code>Enum</code> defined in this class which maps to the correct direction of toggling 
* @see behaviors.multiact.IdentifiedMultiAction#IdentifiedMultiAction(Enum) 
*/ 
public ToggleAnnotationsAction(Direction dir) { 
    super(dir); 
    this.myDir = dir; 
} 

/** 
* Performs the toggling, moving the audio position to the next/previous annotation. 
* 
* Afterward sends an update to all <code>UpdatingActions<code>. 
* 
* Since the waveform display autonomously decides when to paint itself, this action may not result in an instant visual change. 
* 
* <p>Prints warnings if an appropriate Annotation could not be found, despite the action being enabled. 
* 
* @param e The <code>ActionEvent</code> provided by the trigger 
*/ 
public void actionPerformed(ActionEvent e) { 
    //Reset Status to 0 
    status =0; 


    Annotation ann = findAnnotation(myDir, CurAudio.getMaster().framesToMillis(CurAudio.getAudioProgress())); 
    if(ann == null) { 
     System.err.println("It should not have been possible to call " + getClass().getName() + ". Could not find matching annotation"); 
    } 
    else { 
     final long approxFrame = CurAudio.getMaster().millisToFrames(ann.getTime()); 
     final long curFrame = CurAudio.getAudioProgress(); 
     if(approxFrame < 0 || approxFrame > CurAudio.getMaster().durationInFrames() - 1) { 
      GiveMessage.errorMessage("The annotation I am toggling to isn't in range.\nPlease check annotation file for errors."); 
      return; 
     } 

      Timer timer = new Timer(10, new ActionListener() { 
       private long panFrame = curFrame; 
       private long endFrame = approxFrame; 
       public void actionPerformed(ActionEvent evt) { 

        if(myDir == Direction.FORWARD){ 
         if (panFrame >= endFrame) { 

          //How do i Stop my timer here ? 
          return; 
         } 
         CurAudio.setAudioProgressWithoutUpdatingActions(panFrame); 
         panFrame += 4000; 
        } 
       else if(myDir == Direction.BACKWARD){ 
        if (panFrame <= endFrame) { 

         // How do i Stop my timer here ? 
         return; 
        } 
        CurAudio.setAudioProgressWithoutUpdatingActions(panFrame); 
        panFrame -= 4000; 
       } 
      } 

     } 
     ); 

     timer.start(); 

     } 
    MyFrame.getInstance().requestFocusInWindow(); 
} 


/** 
* A forward (backward) <code>ToggleAnnotationsAction</code> should be enabled only when audio is open, not playing, and when there is an annotation following (preceding) the current position. 
*/ 
@Override 
public void update() { 
    if(CurAudio.audioOpen()) { 
     if(CurAudio.getPlayer().getStatus() == PrecisionPlayer.Status.PLAYING) { 
      setEnabled(false); 
     } 
     else { 
      double curTimeMillis = CurAudio.getMaster().framesToMillis(CurAudio.getAudioProgress()); 
      if(findAnnotation(myDir, curTimeMillis) != null) { 
       setEnabled(true); 
      } 
      else { 
       setEnabled(false); 
      } 
     } 
    } 
    else { 
     setEnabled(false); 
    } 
} 

/** 
* Finds the next/previous <code>Annotation</code> relative to a certain audio position in milliseconds. 
* 
* @param dir The direction of movement 
* @param curTimeMillis The present time in milliseconds 
* 
* @return In principle, the <code>Annotation</code> after/before <code>curTimeMillis</code> 
*/ 
private Annotation findAnnotation(Direction dir, double curTimeMillis) { 
    Annotation[] anns = AnnotationDisplay.getAnnotationsInOrder(); 
    if(myDir == Direction.FORWARD) { 
     for(int i = 0; i < anns.length; i++) { 
      if(anns[i].getTime() - curTimeMillis > 1) { 
       return anns[i]; 
      } 
     } 
    } 
    else { 
     for(int i = anns.length - 1; i >= 0; i--) { 
      if(curTimeMillis - anns[i].getTime() > 1) { 
       return anns[i]; 
      } 
     } 
    } 
    return null; 
} 

}

由於提前 克里希南

回答

42

也是可能的:

final Timer timer = new Timer(10, null); 
timer.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent evt) { 
     (as in the question, except that you can refer to timer here) 
    } 
}); 

或者,使用事件對象獲取源代碼(然後將其丟,):

final Timer timer = new Timer(10, new ActionListener() { 
    public void actionPerformed(ActionEvent evt) { 
     ((Timer)evt.getSource()).stop(); 
    } 
}); 

或者,保持計時器在一個實例變量,你可以從你的處理程序中引用它還是有處理程序調用你的類中的方法,該方法可以停止/啓動。

+0

謝謝賈斯汀。創建一個空ActionListener,然後更新它的工作就好了。 – Krishnan 2010-10-05 14:26:37

+0

精彩的解決方案!我正在爲此準備。 – bhavesh 2014-05-15 18:25:53

+0

它仍然是實際的。 :) – GreyGoblin 2017-06-27 12:48:16

4

趣味的問題。

您必須使Timer最終在您要停止它的匿名ActionListener中訪問它。但是匿名ActionListener仍然不會編譯,因爲Timer尚未初始化。

請注意,計時器可能不是您在此處的最佳選擇。但爲了使其工作,我會將Timer包裝在內部類中。

在你ToggleAnnotationsAction.actionPerformed()方法添加一行:

MyTimer timer = new MyTimer(); 
timer.start(); 

那麼可以使用這樣的一類,與定時器的ActionListener的代碼替換我的簡單的ActionListener代碼:

private class MyTimer implements ActionListener{ 
    private Timer timer; 

    private MyTimer(){ 
    timer = new Timer(10, this); 
    } 

    public void start(){ 
    timer.start(); 
    } 

    public void stop(){ 
    timer.stop(); 
    } 

    public void actionPerformed(ActionEvent e){ 
    if(isTimeToStop()){ 
     stop(); 
    } 
    } 

    public boolean isTimeToStop(){ 
    return true; 
    } 
} 
+1

+1你擊敗了我33秒! :-) – trashgod 2010-10-04 21:47:18

+0

謝謝,這真的很有幫助! – ebi 2013-04-14 14:24:22