The Java Tutorials have been written for JDK 8.Java教程是为JDK 8编写的。Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.本页中描述的示例和实践没有利用后续版本中引入的改进,并且可能使用不再可用的技术。See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息,请参阅JDK发行说明。
A Swing timer (an instance of Swing计时器(javax.swing.Timer
) fires one or more action events after a specified delay. javax.swing.Timer
的实例)在指定的延迟之后触发一个或多个动作事件。Do not confuse Swing timers with the general-purpose timer facility in the 不要将Swing计时器与java.util
package. java.util
包中的通用计时器功能混淆。This page describes only Swing timers.本页仅介绍Swing计时器。
In general, we recommend using Swing timers rather than general-purpose timers for GUI-related tasks because Swing timers all share the same, pre-existing timer thread and the GUI-related task automatically executes on the event-dispatch thread. 一般来说,我们建议使用Swing计时器而不是通用计时器来执行与GUI相关的任务,因为Swing计时器都共享相同的、预先存在的计时器线程,并且GUI相关任务会在事件分派线程上自动执行。However, you might use a general-purpose timer if you don't plan on touching the GUI from the timer, or need to perform lengthy processing.但是,如果您不打算从计时器中触摸GUI,或者需要执行冗长的处理,则可以使用通用计时器。
You can use Swing timers in two ways:您可以通过两种方式使用Swing计时器:
Swing timers are very easy to use. When you create the timer, you specify an action listener to be notified when the timer "goes off". 摇摆计时器非常容易使用。当您创建计时器时,您指定了一个动作监听器,当计时器“关闭”时将收到通知。The 此侦听器中的actionPerformed
method in this listener should contain the code for whatever task you need to be performed. actionPerformed
方法应包含需要执行的任何任务的代码。When you create the timer, you also specify the number of milliseconds between timer firings. 创建计时器时,还可以指定计时器触发之间的毫秒数。If you want the timer to go off only once, you can invoke 如果希望计时器只关闭一次,可以在计时器上调用setRepeats(false)
on the timer. setRepeats(false)
。To start the timer, call its 要启动计时器,请调用其start
method. start
方法。To suspend it, call 要暂停,请调用stop
.stop
方法。
Note that the Swing timer's task is performed in the event dispatch thread. 请注意,Swing计时器的任务在事件分派线程中执行。This means that the task can safely manipulate components, but it also means that the task should execute quickly. 这意味着任务可以安全地操作组件,但也意味着任务应该快速执行。If the task might take a while to execute, then consider using a 如果任务可能需要一段时间才能执行,那么可以考虑使用SwingWorker
instead of or in addition to the timer. SwingWorker
来代替计时器或在计时器之外使用它。See Concurrency in Swing for instructions about using the 有关使用SwingWorker
class and information on using Swing components in multi-threaded programs.SwingWorker
类的说明以及在多线程程序中使用Swing组件的信息,请参阅Swing中的并发。
Let's look at an example of using a timer to periodically update a component. 让我们看一个使用计时器定期更新组件的示例。The TumbleItem
applet uses a timer to update its display at regular intervals. TumbleItem
小程序使用计时器定期更新其显示。(To see this applet running, go to How to Make Applets. (要查看此小程序正在运行,请转到如何制作小程序。This applet begins by creating and starting a timer:此小程序首先创建并启动计时器:
timer = new Timer(speed, this); timer.setInitialDelay(pause); timer.start();
The speed
and pause
variables represent applet parameters; as configured on the other page, these are 100 and 1900 respectively, so that the first timer event will occur in approximately 1.9 seconds, and recur every 0.1 seconds. speed
和pause
变量表示小程序参数;如另一页上所配置的,这两个值分别为100和1900,因此第一个计时器事件将在大约1.9秒内发生,并且每0.1秒重复一次。By specifying 通过将其指定为this
as the second argument to the Timer
constructor, TumbleItem
specifies that it is the action listener for timer events.Timer
构造函数的第二个参数,TumbleItem
指定它是计时器事件的动作监听器。
After starting the timer, 启动计时器后,TumbleItem
begins loading a series of images in a background thread. Meanwhile, the timer events begin to occur, causing the actionPerformed
method to execute:TumbleItem
开始在后台线程中加载一系列图像。同时,计时器事件开始发生,导致actionPerformed
方法执行:
public void actionPerformed(ActionEvent e) { //If still loading, can't animate. 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(); } }
Until the images are loaded, 在加载图像之前,worker.isDone
returns false
, so timer events are effectively ignored. worker.isDone
返回false
,因此计时器事件实际上被忽略。The first part of the event handling code simply sets values that are employed in the animation control's 事件处理代码的第一部分只是设置动画控件的paintComponent
method: loopslot
(the index of the next graphic in the animation) and off
(the horizontal offset of the next graphic).paintComponent
方法中使用的值:loopslot
(动画中下一个图形的索引)和off
(下一个图像的水平偏移)。
Eventually, 最终,loopslot
will reach the end of the image array and start over. loopslot
将到达图像数组的末尾并重新开始。When this happens, the code at the end of 发生这种情况时,actionPerformed
restarts the timer. actionPerformed
末尾的代码将重新启动计时器。Doing this causes a short delay before the animation sequence begins again.这样做会导致动画序列再次开始之前的短暂延迟。