本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
末尾的代码重新启动计时器。这样做会导致动画序列重新开始之前的短暂延迟。