Documentation

The Java™ Tutorials
Hide TOC
How to Use Swing Timers如何使用Swing计时器
Trail: Creating a GUI With Swing
Lesson: Using Other Swing Features

How to Use Swing Timers如何使用回转计时器

A Swing timer (an instance of javax.swing.Timer) fires one or more action events after a specified delay. Swing计时器(javax.swing.Timer的实例)在指定的延迟之后触发一个或多个动作事件。Do not confuse Swing timers with the general-purpose timer facility in the java.util package. 不要将Swing计时器与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. speedpause变量表示小程序参数;如另一页上所配置的,这两个值分别为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.这样做会导致动画序列再次开始之前的短暂延迟。


Previous page: How to Use Actions
Next page: How to Support Assistive Technologies