2010-10-04 11 views
25

Sto provando a fermare un timer all'interno di ActionListener. Di seguito è riportato il codice di ciò che sto cercando di fare. Sto cercando di fermare il timer che ho creato quando una certa condizione è soddisfatta all'interno del metodo actionPerformed. timer.stop() non funziona, il compilatore non mi permette di farlo.Stop a swing Timer dall'interno del Listener di azioni

Qualsiasi aiuto. suggerimento, il consiglio sarebbe davvero utile.

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; 
} 

}

Grazie in anticipo Krishnan

risposta

42

Anche possibile:

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) 
    } 
}); 

Oppure utilizzare l'oggetto evento per ottenere l'origine (E gettalo via, boo):

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

Oppure, tenere il timer in una variabile di istanza e si può fare riferimento a esso dal vostro gestore o hanno il gestore di chiamare un metodo sulla classe che potrebbe fermare/avviarlo .

+0

Grazie Justin. Creare un ActionListener null e quindi aggiornarlo funziona perfettamente. – Krishnan

+0

Soluzione meravigliosa! Stavo cercando esattamente questo. – bhavesh

+0

È ancora attuale. :) – GreyGoblin

4

problema Fun.

È necessario impostare il timer finale per accedervi nell'anonimo ActionListener in cui si desidera interromperlo. Tuttavia, ActionListener anonimo non verrà compilato poiché il timer non è ancora stato inizializzato.

Si noti che un timer potrebbe non essere la scelta migliore qui. Ma per fare in modo che tutto funzioni così, avvolgere il timer in una classe interiore.

nel metodo ToggleAnnotationsAction.actionPerformed() aggiungere una linea come:

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

Quindi potrebbe essere utilizzato una classe come questa, sostituendo il mio codice ActionListener semplice con il codice ActionListener del Timer:

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 Mi hai battuto di 33 secondi! :-) – trashgod

+0

Grazie, questo è davvero utile! – ebi

Problemi correlati