如果您想坚持使用 Timer 课程,您可以执行以下操作:
public class TimerExample {
private final Timer timer = new Timer();
private TimerTask timerTask;
public void setUpButton(Button btn, Circle cir) {
btn.addEventHandler(MouseEvent.MOUSE_PRESSED, me -> {
timerTask = new TimerTask() {
@Override
public void run() {
Platform.runLater(()
-> circle.setTranslateX(circle.getTranslateX() + 1);
}
};
timer.schedule(timerTask, 0L, 10L);
});
btn.addEventHandler(MouseEvent.MOUSE_RELEASED, me -> {
timerTask.cancel();
timerTask = null;
timer.purge(); // So TimerTasks don't build up inside the Timer
// I'm not 100% sure this must/should be called
// every time
});
}
}
使用Timer 时,您必须安排TimerTasks 使用它。如您所见,我使用了timer.schedule(timerTask, 0L, 10L),这意味着timerTask 将在0 milliseconds 的初始延迟之后运行,然后是每个10 milliseconds。此调度发生在按下按钮时。释放鼠标时,TimerTask 被取消(不会再次运行),然后我将变量设置为 null 并清除 Timer 以删除对 TimerTask 的任何引用。
在run 方法中,您必须操作Platform.runLater(Runnable) 中的圆圈,因为不会在FxApplication 线程上调用TimerTask。
就个人而言,如果坚持使用计时器之类的东西,我更愿意使用javafx.animation.AnimationTimer。这是因为AnimationTimer 的handle(long) 方法在FxApplication 线程上每帧调用一次。
类似这样的:
public class AnimationTimerExample {
public void setUpButton(Button btn, Circle circle) {
AnimationTimer timer = new AnimationTimer() {
private final long delay = 10_000_000L; // This must be in
// nanoseconds
// since "now" is in
// nanoseconds
private long lastExecution;
@Override
public void handle(long now) {
if (now - (lastExecution + delay) <= 0L {
// Move circle
lastExecution = now;
}
}
};
btn.addEventHandler(MouseEvent.MOUSE_PRESSED, me -> timer.start());
btn.addEventHandler(MouseEvent.MOUSE_RELEASED, me -> timer.stop());
}
}
这里你必须根据延迟手动计算何时运行,但这可以避免任何线程问题。