Java 从动作侦听器内部停止摆动计时器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3858920/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Stop a swing Timer from inside the Action Listener
提问by Krishnan
I'm trying to stop a timer inside the the ActionListener. Below is the code of what i'm trying to do. I'm tring to stop the timer i created when a certain condition is met inside the actionPerformed method. timer.stop() does not work , the compiler does not let me do that.
我正在尝试停止 ActionListener 中的计时器。下面是我正在尝试做的代码。当 actionPerformed 方法中满足某个条件时,我试图停止我创建的计时器。timer.stop() 不起作用,编译器不允许我这样做。
Any help . suggestion , advice would be really helpful.
任何帮助。建议,建议会非常有帮助。
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;
}
}
}
Thanks in Advance Krishnan
在此先感谢克里希南
采纳答案by Justin W
Also possible:
也可以:
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)
}
});
Or, use the event object to get the source (and cast it, boo):
或者,使用事件对象获取源(并转换它,boo):
final Timer timer = new Timer(10, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
((Timer)evt.getSource()).stop();
}
});
Or, keep the timer in an instance variable and you can reference it from your handler or have the handler call a method on your class which could stop/start it.
或者,将计时器保存在一个实例变量中,您可以从处理程序中引用它,或者让处理程序在您的类上调用一个可以停止/启动它的方法。
回答by Steve Hymanson
Fun problem.
有趣的问题。
You have to make Timer final to access it in the anonymous ActionListener you want to stop it in. But the anonymous ActionListener still won't compile because the Timer hasn't been initialized yet.
您必须使 Timer final 在您想要停止它的匿名 ActionListener 中访问它。但匿名 ActionListener 仍然不会编译,因为 Timer 尚未初始化。
Note that a Timer may not be your best choice here. But to make this work as is, I'd wrap the Timer in an inner class.
请注意,计时器可能不是您的最佳选择。但是为了按原样工作,我将 Timer 包装在一个内部类中。
In your ToggleAnnotationsAction.actionPerformed()
method add a line like:
在您的ToggleAnnotationsAction.actionPerformed()
方法中添加如下一行:
MyTimer timer = new MyTimer();
timer.start();
Then a class like this could be used, replacing my simple ActionListener code with your Timer's ActionListener code:
然后可以使用这样的类,用您的 Timer 的 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;
}
}