2010-10-04 16 views
25

Estoy intentando detener un temporizador dentro del ActionListener. A continuación se muestra el código de lo que estoy tratando de hacer. Estoy intentando detener el temporizador que creé cuando se cumple una determinada condición dentro del método actionPerformed. timer.stop() no funciona, el compilador no me deja hacer eso.Detener un temporizador de oscilación desde el interior del Oyente de acción

Cualquier ayuda. sugerencia, consejo sería realmente útil.

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

}

Gracias de antemano Krishnan

Respuesta

42

También es posible:

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

O use el objeto de evento para obtener la fuente (Y su emisión, Boo):

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

O, mantenga el contador de tiempo en una variable de instancia y se puede hacer referencia a ella desde su manejador o tener el controlador de llamar a un método en su clase que podría arranque/parada se .

+0

Gracias Justin. Crear un ActionListener nulo y luego actualizarlo funciona bien. – Krishnan

+0

¡Solución maravillosa! Estaba buscando exactamente esto. – bhavesh

+0

Todavía es real. :) – GreyGoblin

4

problema diversión.

Tienes que hacer que el temporizador sea definitivo para acceder a él en el ActionListener anónimo en el que deseas detenerlo. Pero el ActionListener anónimo aún no compilará porque el temporizador aún no se ha inicializado.

Tenga en cuenta que un temporizador puede no ser su mejor opción aquí. Pero para hacer que esto funcione como está, envolvería el temporizador en una clase interna.

En el método de ToggleAnnotationsAction.actionPerformed() añadir una línea como:

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

Entonces se podría utilizar una clase como esta, en sustitución de mi código simple ActionListener con su código ActionListener del temporizador:

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 ¡Me has vencido por 33 segundos! :-) – trashgod

+0

¡Gracias, esto es realmente útil! – ebi

Cuestiones relacionadas