本Java教程适用于JDK 8。本页面中描述的示例和实践不利用后续版本中引入的改进,并可能使用已不再可用的技术。
请查看Java语言更改以获取Java SE 9及后续版本中更新的语言特性的摘要。
请查看JDK发行说明以获取有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息。
Swing计时器(javax.swing.Timer的一个实例)在指定的延迟后触发一个或多个动作事件。不要将Swing计时器与java.util包中的通用计时器混淆。本页面仅描述Swing计时器。
一般而言,我们建议在GUI相关任务中使用Swing计时器而不是通用计时器,因为Swing计时器共享同一个预先存在的计时器线程,并且GUI相关任务会自动在事件分派线程上执行。但是,如果您不打算从计时器中操作GUI,或者需要执行长时间处理任务,可以使用通用计时器。
您可以以两种方式使用Swing计时器:
使用Swing计时器非常简单。创建计时器时,您需要指定一个操作监听器,在计时器"触发"时通知该监听器。该监听器中的actionPerformed方法应包含您需要执行的任务的代码。创建计时器时,您还需要指定计时器触发之间的毫秒数。如果您只希望计时器触发一次,可以在计时器上调用setRepeats(false)。要启动计时器,请调用其start方法。要暂停计时器,请调用stop。
请注意,Swing计时器的任务在事件分派线程中执行。这意味着任务可以安全地操作组件,但也意味着任务应该执行得很快。如果任务可能需要一段时间来执行,请考虑使用SwingWorker来替代或附加在计时器上。有关使用SwingWorker类的说明以及在多线程程序中使用Swing组件的信息,请参见Swing中的并发。
让我们看一个使用计时器定期更新组件的示例。 小程序使用计时器定期更新其显示。(要查看此小程序的运行情况,请转到如何制作小程序。该小程序首先创建并启动一个计时器:TumbleItem
timer = new Timer(speed, this); timer.setInitialDelay(pause); timer.start();
speed和pause变量表示applet参数;在另一页上配置的值分别为100和1900,所以第一个计时器事件将在约1.9秒后发生,并且每0.1秒重复一次。通过将this作为第二个参数传递给Timer构造函数,TumbleItem指定它是计时器事件的动作监听器。
在启动计时器之后,TumbleItem开始在后台线程中加载一系列图像。同时,计时器事件开始发生,导致actionPerformed方法执行:
public void actionPerformed(ActionEvent e) {
//如果还在加载中,无法进行动画。
if (!worker.isDone()) {
return;
}
loopslot++;
if (loopslot >= nimgs) {
loopslot = 0;
off += offset;
if (off < 0) {
off = width - maxWidth;
} else if (off + maxWidth > width) {
off = 0;
}
}
animator.repaint();
if (loopslot == nimgs - 1) {
timer.restart();
}
}
在图像加载完成之前,worker.isDone返回false,因此计时器事件被有效地忽略。事件处理代码的第一部分简单地设置了在动画控制的paintComponent方法中使用的值:loopslot(动画中下一个图形的索引)和off(下一个图形的水平偏移量)。
最终,loopslot将到达图像数组的末尾并重新开始。当这种情况发生时,actionPerformed末尾的代码重新启动计时器。这样做会导致动画序列重新开始之前的短暂延迟。