2010-10-04 41 views
25

Tôi đang cố dừng bộ đếm thời gian bên trong ActionListener. Dưới đây là mã của những gì tôi đang cố gắng làm. Tôi đang tring để dừng timer tôi tạo ra khi một điều kiện nhất định được đáp ứng bên trong phương thức actionPerformed. timer.stop() không hoạt động, trình biên dịch không cho phép tôi làm điều đó.Dừng đồng hồ bấm giờ từ bên trong Trình nghe hành động

Bất kỳ trợ giúp nào. gợi ý, lời khuyên sẽ thực sự hữu ích.

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

}

Cảm ơn trước Krishnan

Trả lời

42

Cũng có thể:

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

Hoặc, sử dụng đối tượng sự kiện để lấy nguồn (Và đúc nó, boo):

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

Hoặc, giữ bộ đếm thời gian trong một biến dụ và bạn có thể tham khảo nó từ xử lý của bạn hoặc có xử lý gọi một phương thức trên lớp của bạn có thể dừng/khởi động nó .

+0

Cảm ơn Justin. Tạo một ActionListener null và sau đó cập nhật nó hoạt động tốt. – Krishnan

+0

Giải pháp tuyệt vời! Tôi đã tìm kiếm chính xác điều này. – bhavesh

+0

Nó vẫn còn thực tế. :) – GreyGoblin

4

vấn đề Fun.

Bạn phải đặt hẹn giờ cuối cùng để truy cập vào Bộ đệm hành động ẩn danh mà bạn muốn dừng trong đó. Tuy nhiên, ActionListener ẩn danh vẫn không biên dịch vì Bộ tính giờ chưa được khởi tạo.

Lưu ý rằng Bộ hẹn giờ có thể không phải là lựa chọn tốt nhất của bạn tại đây. Nhưng để thực hiện công việc này, tôi sẽ quấn Timer vào một lớp bên trong.

Trong phương pháp ToggleAnnotationsAction.actionPerformed() bạn thêm một dòng như:

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

Sau đó, một lớp học như thế này có thể được sử dụng, thay thế mã ActionListener đơn giản của tôi với mã ActionListener hẹn giờ của bạn:

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 Bạn đã đánh bại tôi sau 33 giây! :-) – trashgod

+0

Cảm ơn, điều này thực sự hữu ích! – ebi

Các vấn đề liên quan