2010-10-04 14 views
25

Próbuję zatrzymać timer wewnątrz ActionListener. Poniżej znajduje się kod tego, co próbuję zrobić. Próbuję zatrzymać zegar, który utworzyłem, gdy pewien warunek zostanie spełniony w metodzie actionPerformed. timer.stop() nie działa, kompilator nie pozwala mi tego zrobić.Zatrzymaj swing Timer z wnętrza odbiornika akcji

Każda pomoc. sugestia, porady byłyby naprawdę pomocne.

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

}

Dzięki z góry Krishnan

Odpowiedz

42

także możliwe:

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

Lub użyj obiektu zdarzenia, aby uzyskać źródło (I rzucić go, boo):

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

Albo zachować czasomierz w zmiennej instancji i można odwołać go z obsługi lub masz handler wywołać metodę w swojej klasie, który mógłby zatrzymać/uruchomić .

+0

Dzięki Justin. Tworzenie pustego ActionListener, a następnie jego aktualizacja działa dobrze. – Krishnan

+0

Cudowne rozwiązanie! Szukałem właśnie tego. – bhavesh

+0

To wciąż aktualne. :) – GreyGoblin

4

Fun problemu.

Musisz zrobić Timer końcowy, aby uzyskać do niego dostęp w anonimowym ActionListener, który chcesz zatrzymać. Ale anonimowy ActionListener nadal nie będzie się kompilował, ponieważ Timer nie został jeszcze zainicjowany.

Należy pamiętać, że Timer może nie być najlepszym wyborem. Ale żeby sprawić, by działało jak jest, zawinęłbym Timer w wewnętrzną klasę.

W swojej metodzie ToggleAnnotationsAction.actionPerformed() dodać linię jak:

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

to może być używane klasy tak, zastępując mój prosty kod ActionListener z kodem ActionListener Timera:

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 Pokonałeś mnie o 33 sekundy! :-) – trashgod

+0

Dzięki, to jest naprawdę pomocne! – ebi