Source Code Cross Referenced for Timer.java in  » 6.0-JDK-Core » swing » javax » swing » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » swing » javax.swing 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package javax.swing;
027
028        import java.util.*;
029        import java.util.concurrent.atomic.AtomicBoolean;
030        import java.util.concurrent.locks.*;
031        import java.awt.*;
032        import java.awt.event.*;
033        import java.io.Serializable;
034        import javax.swing.event.EventListenerList;
035
036        /**
037         * Fires one or more {@code ActionEvent}s at specified
038         * intervals. An example use is an animation object that uses a
039         * <code>Timer</code> as the trigger for drawing its frames.
040         *<p>
041         * Setting up a timer
042         * involves creating a <code>Timer</code> object,
043         * registering one or more action listeners on it,
044         * and starting the timer using
045         * the <code>start</code> method.
046         * For example, 
047         * the following code creates and starts a timer
048         * that fires an action event once per second
049         * (as specified by the first argument to the <code>Timer</code> constructor).
050         * The second argument to the <code>Timer</code> constructor
051         * specifies a listener to receive the timer's action events.
052         *
053         *<pre>
054         *  int delay = 1000; //milliseconds
055         *  ActionListener taskPerformer = new ActionListener() {
056         *      public void actionPerformed(ActionEvent evt) {
057         *          <em>//...Perform a task...</em>
058         *      }
059         *  };
060         *  new Timer(delay, taskPerformer).start();</pre>
061         *
062         * <p>
063         * {@code Timers} are constructed by specifying both a delay parameter
064         * and an {@code ActionListener}. The delay parameter is used
065         * to set both the initial delay and the delay between event
066         * firing, in milliseconds. Once the timer has been started,
067         * it waits for the initial delay before firing its
068         * first <code>ActionEvent</code> to registered listeners.
069         * After this first event, it continues to fire events
070         * every time the between-event delay has elapsed, until it
071         * is stopped.
072         * <p>
073         * After construction, the initial delay and the between-event
074         * delay can be changed independently, and additional
075         * <code>ActionListeners</code> may be added.
076         * <p>
077         * If you want the timer to fire only the first time and then stop,
078         * invoke <code>setRepeats(false)</code> on the timer.
079         * <p>
080         * Although all <code>Timer</code>s perform their waiting
081         * using a single, shared thread 
082         * (created by the first <code>Timer</code> object that executes),
083         * the action event handlers for <code>Timer</code>s
084         * execute on another thread -- the event-dispatching thread.
085         * This means that the action handlers for <code>Timer</code>s
086         * can safely perform operations on Swing components.
087         * However, it also means that the handlers must execute quickly
088         * to keep the GUI responsive.
089         *
090         * <p>
091         * In v 1.3, another <code>Timer</code> class was added
092         * to the Java platform: <code>java.util.Timer</code>.
093         * Both it and <code>javax.swing.Timer</code>
094         * provide the same basic functionality,
095         * but <code>java.util.Timer</code> 
096         * is more general and has more features.
097         * The <code>javax.swing.Timer</code> has two features
098         * that can make it a little easier to use with GUIs.
099         * First, its event handling metaphor is familiar to GUI programmers
100         * and can make dealing with the event-dispatching thread
101         * a bit simpler.
102         * Second, its
103         * automatic thread sharing means that you don't have to 
104         * take special steps to avoid spawning
105         * too many threads.
106         * Instead, your timer uses the same thread
107         * used to make cursors blink,
108         * tool tips appear, 
109         * and so on.
110         *
111         * <p>
112         * You can find further documentation
113         * and several examples of using timers by visiting
114         * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/timer.html"
115         * target = "_top">How to Use Timers</a>,
116         * a section in <em>The Java Tutorial.</em>
117         * For more examples and help in choosing between
118         * this <code>Timer</code> class and 
119         * <code>java.util.Timer</code>, 
120         * see 
121         * <a href="http://java.sun.com/products/jfc/tsc/articles/timer/"
122         * target="_top">Using Timers in Swing Applications</a>,
123         * an article in <em>The Swing Connection.</em>
124         * <p>
125         * <strong>Warning:</strong>
126         * Serialized objects of this class will not be compatible with
127         * future Swing releases. The current serialization support is
128         * appropriate for short term storage or RMI between applications running
129         * the same version of Swing.  As of 1.4, support for long term storage
130         * of all JavaBeans<sup><font size="-2">TM</font></sup>
131         * has been added to the <code>java.beans</code> package.
132         * Please see {@link java.beans.XMLEncoder}.
133         *
134         * @see java.util.Timer <code>java.util.Timer</code>
135         *
136         *
137         * @version 1.56 05/05/07
138         * @author Dave Moore
139         */
140        public class Timer implements  Serializable {
141            /*
142             * NOTE: all fields need to be handled in readResolve
143             */
144
145            protected EventListenerList listenerList = new EventListenerList();
146
147            // The following field strives to maintain the following:
148            //    If coalesce is true, only allow one Runnable to be queued on the
149            //    EventQueue and be pending (ie in the process of notifying the
150            //    ActionListener). If we didn't do this it would allow for a
151            //    situation where the app is taking too long to process the
152            //    actionPerformed, and thus we'ld end up queing a bunch of Runnables
153            //    and the app would never return: not good. This of course implies
154            //    you can get dropped events, but such is life.
155            // notify is used to indicate if the ActionListener can be notified, when
156            // the Runnable is processed if this is true it will notify the listeners.
157            // notify is set to true when the Timer fires and the Runnable is queued.
158            // It will be set to false after notifying the listeners (if coalesce is
159            // true) or if the developer invokes stop.
160            private transient final AtomicBoolean notify = new AtomicBoolean(
161                    false);
162
163            private volatile int initialDelay, delay;
164            private volatile boolean repeats = true, coalesce = true;
165
166            private transient final Runnable doPostEvent;
167
168            private static volatile boolean logTimers;
169
170            private transient final Lock lock = new ReentrantLock();
171
172            // This field is maintained by TimerQueue.
173            // eventQueued can also be reset by the TimerQueue, but will only ever
174            // happen in applet case when TimerQueues thread is destroyed.
175            // access to this field is synchronized on getLock() lock.
176            transient TimerQueue.DelayedTimer delayedTimer = null;
177
178            private volatile String actionCommand;
179
180            /**
181             * Creates a {@code Timer} and initializes both the initial delay and
182             * between-event delay to {@code delay} milliseconds. If {@code delay}
183             * is less than or equal to zero, the timer fires as soon as it
184             * is started. If <code>listener</code> is not <code>null</code>,
185             * it's registered as an action listener on the timer.
186             *
187             * @param delay milliseconds for the initial and between-event delay
188             * @param listener  an initial listener; can be <code>null</code>
189             *
190             * @see #addActionListener
191             * @see #setInitialDelay
192             * @see #setRepeats
193             */
194            public Timer(int delay, ActionListener listener) {
195                super ();
196                this .delay = delay;
197                this .initialDelay = delay;
198
199                doPostEvent = new DoPostEvent();
200
201                if (listener != null) {
202                    addActionListener(listener);
203                }
204            }
205
206            /**
207             * DoPostEvent is a runnable class that fires actionEvents to 
208             * the listeners on the EventDispatchThread, via invokeLater.
209             * @see Timer#post
210             */
211            class DoPostEvent implements  Runnable {
212                public void run() {
213                    if (logTimers) {
214                        System.out.println("Timer ringing: " + Timer.this );
215                    }
216                    if (notify.get()) {
217                        fireActionPerformed(new ActionEvent(Timer.this , 0,
218                                getActionCommand(), System.currentTimeMillis(),
219                                0));
220                        if (coalesce) {
221                            cancelEvent();
222                        }
223                    }
224                }
225
226                Timer getTimer() {
227                    return Timer.this ;
228                }
229            }
230
231            /**
232             * Adds an action listener to the <code>Timer</code>.
233             *
234             * @param listener the listener to add
235             * 
236             * @see #Timer
237             */
238            public void addActionListener(ActionListener listener) {
239                listenerList.add(ActionListener.class, listener);
240            }
241
242            /**
243             * Removes the specified action listener from the <code>Timer</code>.
244             *
245             * @param listener the listener to remove
246             */
247            public void removeActionListener(ActionListener listener) {
248                listenerList.remove(ActionListener.class, listener);
249            }
250
251            /**
252             * Returns an array of all the action listeners registered
253             * on this timer.
254             *
255             * @return all of the timer's <code>ActionListener</code>s or an empty
256             *         array if no action listeners are currently registered
257             *
258             * @see #addActionListener
259             * @see #removeActionListener
260             *
261             * @since 1.4
262             */
263            public ActionListener[] getActionListeners() {
264                return (ActionListener[]) listenerList
265                        .getListeners(ActionListener.class);
266            }
267
268            /**
269             * Notifies all listeners that have registered interest for
270             * notification on this event type.  
271             *
272             * @param e the action event to fire
273             * @see EventListenerList
274             */
275            protected void fireActionPerformed(ActionEvent e) {
276                // Guaranteed to return a non-null array
277                Object[] listeners = listenerList.getListenerList();
278
279                // Process the listeners last to first, notifying
280                // those that are interested in this event
281                for (int i = listeners.length - 2; i >= 0; i -= 2) {
282                    if (listeners[i] == ActionListener.class) {
283                        ((ActionListener) listeners[i + 1]).actionPerformed(e);
284                    }
285                }
286            }
287
288            /**
289             * Returns an array of all the objects currently registered as
290             * <code><em>Foo</em>Listener</code>s
291             * upon this <code>Timer</code>.
292             * <code><em>Foo</em>Listener</code>s
293             * are registered using the <code>add<em>Foo</em>Listener</code> method.
294             * <p>
295             * You can specify the <code>listenerType</code> argument
296             * with a class literal, such as <code><em>Foo</em>Listener.class</code>.
297             * For example, you can query a <code>Timer</code> 
298             * instance <code>t</code>
299             * for its action listeners
300             * with the following code:
301             *
302             * <pre>ActionListener[] als = (ActionListener[])(t.getListeners(ActionListener.class));</pre>
303             *
304             * If no such listeners exist,
305             * this method returns an empty array.
306             *
307             * @param listenerType  the type of listeners requested;
308             *          this parameter should specify an interface
309             *          that descends from <code>java.util.EventListener</code>
310             * @return an array of all objects registered as
311             *          <code><em>Foo</em>Listener</code>s
312             *          on this timer,
313             *          or an empty array if no such 
314             *		listeners have been added
315             * @exception ClassCastException if <code>listenerType</code> doesn't
316             *          specify a class or interface that implements 
317             *		<code>java.util.EventListener</code>
318             * 
319             * @see #getActionListeners
320             * @see #addActionListener
321             * @see #removeActionListener
322             *
323             * @since 1.3
324             */
325            public <T extends EventListener> T[] getListeners(
326                    Class<T> listenerType) {
327                return listenerList.getListeners(listenerType);
328            }
329
330            /**
331             * Returns the timer queue.
332             */
333            private TimerQueue timerQueue() {
334                return TimerQueue.sharedInstance();
335            }
336
337            /**
338             * Enables or disables the timer log. When enabled, a message
339             * is posted to <code>System.out</code> whenever the timer goes off.
340             *
341             * @param flag  <code>true</code> to enable logging
342             * @see #getLogTimers
343             */
344            public static void setLogTimers(boolean flag) {
345                logTimers = flag;
346            }
347
348            /**
349             * Returns <code>true</code> if logging is enabled.
350             *
351             * @return <code>true</code> if logging is enabled; otherwise, false
352             * @see #setLogTimers
353             */
354            public static boolean getLogTimers() {
355                return logTimers;
356            }
357
358            /**
359             * Sets the <code>Timer</code>'s between-event delay, the number of milliseconds
360             * between successive action events. This does not affect the initial delay
361             * property, which can be set by the {@code setInitialDelay} method.
362             *
363             * @param delay the delay in milliseconds
364             * @see #setInitialDelay
365             */
366            public void setDelay(int delay) {
367                if (delay < 0) {
368                    throw new IllegalArgumentException("Invalid delay: "
369                            + delay);
370                } else {
371                    this .delay = delay;
372                }
373            }
374
375            /**
376             * Returns the delay, in milliseconds, 
377             * between firings of action events.
378             *
379             * @see #setDelay
380             * @see #getInitialDelay
381             */
382            public int getDelay() {
383                return delay;
384            }
385
386            /**
387             * Sets the <code>Timer</code>'s initial delay, the time
388             * in milliseconds to wait after the timer is started
389             * before firing the first event. Upon construction, this
390             * is set to be the same as the between-event delay,
391             * but then its value is independent and remains unaffected
392             * by changes to the between-event delay.
393             * 
394             * @param initialDelay the initial delay, in milliseconds
395             * @see #setDelay
396             */
397            public void setInitialDelay(int initialDelay) {
398                if (initialDelay < 0) {
399                    throw new IllegalArgumentException(
400                            "Invalid initial delay: " + initialDelay);
401                } else {
402                    this .initialDelay = initialDelay;
403                }
404            }
405
406            /**
407             * Returns the <code>Timer</code>'s initial delay.
408             *
409             * @see #setInitialDelay
410             * @see #setDelay
411             */
412            public int getInitialDelay() {
413                return initialDelay;
414            }
415
416            /**
417             * If <code>flag</code> is <code>false</code>,
418             * instructs the <code>Timer</code> to send only one
419             * action event to its listeners.
420             *
421             * @param flag specify <code>false</code> to make the timer
422             *             stop after sending its first action event
423             */
424            public void setRepeats(boolean flag) {
425                repeats = flag;
426            }
427
428            /**
429             * Returns <code>true</code> (the default)
430             * if the <code>Timer</code> will send
431             * an action event 
432             * to its listeners multiple times.
433             *
434             * @see #setRepeats
435             */
436            public boolean isRepeats() {
437                return repeats;
438            }
439
440            /**
441             * Sets whether the <code>Timer</code> coalesces multiple pending
442             * <code>ActionEvent</code> firings.
443             * A busy application may not be able
444             * to keep up with a <code>Timer</code>'s event generation,
445             * causing multiple
446             * action events to be queued.  When processed,
447             * the application sends these events one after the other, causing the
448             * <code>Timer</code>'s listeners to receive a sequence of
449             * events with no delay between them. Coalescing avoids this situation
450             * by reducing multiple pending events to a single event.
451             * <code>Timer</code>s
452             * coalesce events by default.
453             *
454             * @param flag specify <code>false</code> to turn off coalescing
455             */
456            public void setCoalesce(boolean flag) {
457                boolean old = coalesce;
458                coalesce = flag;
459                if (!old && coalesce) {
460                    // We must do this as otherwise if the Timer once notified
461                    // in !coalese mode notify will be stuck to true and never
462                    // become false.
463                    cancelEvent();
464                }
465            }
466
467            /**
468             * Returns <code>true</code> if the <code>Timer</code> coalesces
469             * multiple pending action events.
470             *
471             * @see #setCoalesce
472             */
473            public boolean isCoalesce() {
474                return coalesce;
475            }
476
477            /**
478             * Sets the string that will be delivered as the action command
479             * in <code>ActionEvent</code>s fired by this timer.
480             * <code>null</code> is an acceptable value.
481             *
482             * @param command the action command
483             * @since 1.6
484             */
485            public void setActionCommand(String command) {
486                this .actionCommand = command;
487            }
488
489            /**
490             * Returns the string that will be delivered as the action command
491             * in <code>ActionEvent</code>s fired by this timer. May be
492             * <code>null</code>, which is also the default.
493             *
494             * @return the action command used in firing events
495             * @since 1.6
496             */
497            public String getActionCommand() {
498                return actionCommand;
499            }
500
501            /**
502             * Starts the <code>Timer</code>,
503             * causing it to start sending action events
504             * to its listeners.
505             *
506             * @see #stop
507             */
508            public void start() {
509                timerQueue().addTimer(this , getInitialDelay());
510            }
511
512            /**
513             * Returns <code>true</code> if the <code>Timer</code> is running.
514             *
515             * @see #start
516             */
517            public boolean isRunning() {
518                return timerQueue().containsTimer(this );
519            }
520
521            /**
522             * Stops the <code>Timer</code>,
523             * causing it to stop sending action events
524             * to its listeners.
525             *
526             * @see #start
527             */
528            public void stop() {
529                getLock().lock();
530                try {
531                    cancelEvent();
532                    timerQueue().removeTimer(this );
533                } finally {
534                    getLock().unlock();
535                }
536            }
537
538            /**
539             * Restarts the <code>Timer</code>,
540             * canceling any pending firings and causing
541             * it to fire with its initial delay.
542             */
543            public void restart() {
544                getLock().lock();
545                try {
546                    stop();
547                    start();
548                } finally {
549                    getLock().unlock();
550                }
551            }
552
553            /**
554             * Resets the internal state to indicate this Timer shouldn't notify
555             * any of its listeners. This does not stop a repeatable Timer from
556             * firing again, use <code>stop</code> for that.
557             */
558            void cancelEvent() {
559                notify.set(false);
560            }
561
562            void post() {
563                if (notify.compareAndSet(false, true) || !coalesce) {
564                    SwingUtilities.invokeLater(doPostEvent);
565                }
566            }
567
568            Lock getLock() {
569                return lock;
570            }
571
572            /*
573             * We have to use readResolve because we can not initialize final
574             * fields for deserialized object otherwise
575             */
576            private Object readResolve() {
577                Timer timer = new Timer(getDelay(), null);
578                timer.listenerList = listenerList;
579                timer.initialDelay = initialDelay;
580                timer.delay = delay;
581                timer.repeats = repeats;
582                timer.coalesce = coalesce;
583                timer.actionCommand = actionCommand;
584                return timer;
585            }
586        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.