Java/Swing JFC/Timer
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
An applet that counts down from a specified time
/*
* Copyright (c) 2004 David Flanagan. All rights reserved.
* This code is from the book Java Examples in a Nutshell, 3nd Edition.
* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
* You may study, use, and modify it for any non-commercial purpose,
* including teaching and use in open-source projects.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book,
* please visit http://www.davidflanagan.ru/javaexamples3.
*/
import java.applet.AudioClip;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.NumberFormat;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.Timer;
/**
* An applet that counts down from a specified time. When it reaches 00:00, it
* optionally plays a sound and optionally moves the browser to a new page.
* Place the mouse over the applet to pause the count; move it off to resume.
* This class demonstrates most applet methods and features.
*/
public class Countdown extends JApplet implements ActionListener, MouseListener {
long remaining; // How many milliseconds remain in the countdown.
long lastUpdate; // When count was last updated
JLabel label; // Displays the count
Timer timer; // Updates the count every second
NumberFormat format; // Format minutes:seconds with leading zeros
Image image; // Image to display along with the time
AudioClip sound; // Sound to play when we reach 00:00
// Called when the applet is first loaded
public void init() {
// Figure out how long to count for by reading the "minutes" parameter
// defined in a <param> tag inside the <applet> tag. Convert to ms.
String minutes = getParameter("minutes");
if (minutes != null)
remaining = Integer.parseInt(minutes) * 60000;
else
remaining = 600000; // 10 minutes by default
// Create a JLabel to display remaining time, and set some properties.
label = new JLabel();
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setOpaque(true); // So label draws the background color
// Read some parameters for this JLabel object
String font = getParameter("font");
String foreground = getParameter("foreground");
String background = getParameter("background");
String imageURL = getParameter("image");
// Set label properties based on those parameters
if (font != null)
label.setFont(Font.decode(font));
if (foreground != null)
label.setForeground(Color.decode(foreground));
if (background != null)
label.setBackground(Color.decode(background));
if (imageURL != null) {
// Load the image, and save it so we can release it later
image = getImage(getDocumentBase(), imageURL);
// Now display the image in the JLabel.
label.setIcon(new ImageIcon(image));
}
// Now add the label to the applet. Like JFrame and JDialog, JApplet
// has a content pane that you add children to
getContentPane().add(label, BorderLayout.CENTER);
// Get an optional AudioClip to play when the count expires
String soundURL = getParameter("sound");
if (soundURL != null)
sound = getAudioClip(getDocumentBase(), soundURL);
// Obtain a NumberFormat object to convert number of minutes and
// seconds to strings. Set it up to produce a leading 0 if necessary
format = NumberFormat.getNumberInstance();
format.setMinimumIntegerDigits(2); // pad with 0 if necessary
// Specify a MouseListener to handle mouse events in the applet.
// Note that the applet implements this interface itself
addMouseListener(this);
// Create a timer to call the actionPerformed() method immediately,
// and then every 1000 milliseconds. Note we don"t start the timer yet.
timer = new Timer(1000, this);
timer.setInitialDelay(0); // First timer is immediate.
}
// Free up any resources we hold; called when the applet is done
public void destroy() {
if (image != null)
image.flush();
}
// The browser calls this to start the applet running
// The resume() method is defined below.
public void start() {
resume();
} // Start displaying updates
// The browser calls this to stop the applet. It may be restarted later.
// The pause() method is defined below
public void stop() {
pause();
} // Stop displaying updates
// Return information about the applet
public String getAppletInfo() {
return "Countdown applet Copyright (c) 2003 by David Flanagan";
}
// Return information about the applet parameters
public String[][] getParameterInfo() {
return parameterInfo;
}
// This is the parameter information. One array of strings for each
// parameter. The elements are parameter name, type, and description.
static String[][] parameterInfo = {
{ "minutes", "number", "time, in minutes, to countdown from" },
{ "font", "font", "optional font for the time display" },
{ "foreground", "color", "optional foreground color for the time" },
{ "background", "color", "optional background color" },
{ "image", "image URL", "optional image to display next to countdown" },
{ "sound", "sound URL", "optional sound to play when we reach 00:00" },
{ "newpage", "document URL", "URL to load when timer expires" }, };
// Start or resume the countdown
void resume() {
// Restore the time we"re counting down from and restart the timer.
lastUpdate = System.currentTimeMillis();
timer.start(); // Start the timer
}
// Pause the countdown
void pause() {
// Subtract elapsed time from the remaining time and stop timing
long now = System.currentTimeMillis();
remaining -= (now - lastUpdate);
timer.stop(); // Stop the timer
}
// Update the displayed time. This method is called from actionPerformed()
// which is itself invoked by the timer.
void updateDisplay() {
long now = System.currentTimeMillis(); // current time in ms
long elapsed = now - lastUpdate; // ms elapsed since last update
remaining -= elapsed; // adjust remaining time
lastUpdate = now; // remember this update time
// Convert remaining milliseconds to mm:ss format and display
if (remaining < 0)
remaining = 0;
int minutes = (int) (remaining / 60000);
int seconds = (int) ((remaining % 60000) / 1000);
label.setText(format.format(minutes) + ":" + format.format(seconds));
// If we"ve completed the countdown beep and display new page
if (remaining == 0) {
// Stop updating now.
timer.stop();
// If we have an alarm sound clip, play it now.
if (sound != null)
sound.play();
// If there is a newpage URL specified, make the browser
// load that page now.
String newpage = getParameter("newpage");
if (newpage != null) {
try {
URL url = new URL(getDocumentBase(), newpage);
getAppletContext().showDocument(url);
} catch (MalformedURLException ex) {
showStatus(ex.toString());
}
}
}
}
// This method implements the ActionListener interface.
// It is invoked once a second by the Timer object
// and updates the JLabel to display minutes and seconds remaining.
public void actionPerformed(ActionEvent e) {
updateDisplay();
}
// The methods below implement the MouseListener interface. We use
// two of them to pause the countdown when the mouse hovers over the timer.
// Note that we also display a message in the statusline
public void mouseEntered(MouseEvent e) {
pause(); // pause countdown
showStatus("Paused"); // display statusline message
}
public void mouseExited(MouseEvent e) {
resume(); // resume countdown
showStatus(""); // clear statusline
}
// These MouseListener methods are unused.
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
}
Swing Timer Demo
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
/*
* SwingTimerDemo.java
*
* Created on May 2, 2007, 3:25 PM
*
* Copyright (c) 2007, Sun Microsystems, Inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of the TimingFramework project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
*
* @author Chet
*/
public class SwingTimerDemo implements ActionListener {
private static long prevTime = 0;
private static long startTime = 0;
private static final int DELAY = 100;
private static final int DURATION = 5 * DELAY;
private static final int PROCESSING_TIME = 30;
private static final long INITIAL_PROCESSING_TIME = 2 * DELAY;
private static Timer timer = null;
private boolean firstTime = true;
/**
* This method will be called during every tick of the Timers.
* We insert an artificial delay each time, to simulate some processing.
* The first time through, this delay is greater than the delay between
* timing events, so that we can see how this hiccup is handled by
* fixed-rate and fixed-delay timers.
*/
public void actionPerformed(ActionEvent ae) {
long nowTime = System.currentTimeMillis();
long elapsedTime = nowTime - prevTime;
long totalTime = nowTime - startTime;
System.out.println("Elapsed time = " + elapsedTime);
if (totalTime > DURATION) {
timer.stop();
}
prevTime = nowTime;
try {
if (firstTime) {
Thread.sleep(INITIAL_PROCESSING_TIME);
firstTime = false;
} else {
Thread.sleep(PROCESSING_TIME);
}
} catch (Exception e) {}
}
public SwingTimerDemo() {
firstTime = true;
}
public static void main(String[] args) {
// Run a default fixed-delay timer
timer = new Timer(DELAY, new SwingTimerDemo());
startTime = prevTime = System.currentTimeMillis();
System.out.println("Fixed Delay Times");
timer.start();
// Sleep for long enough that the first timer ends
try {
Thread.sleep(DURATION*2);
} catch (Exception e) {}
// Run a timer with no coalescing to get fixed-rate behavior
timer = new Timer(DELAY, new SwingTimerDemo());
startTime = prevTime = System.currentTimeMillis();
timer.setCoalesce(false);
System.out.println("\nFixed Rate Times");
timer.start();
}
}
Tick Tock with an Inner Class
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JOptionPane;
import javax.swing.Timer;
public class TickTockInner {
public static void main(String[] args) {
TickTockInner t = new TickTockInner();
t.go();
}
private void go() {
Timer t = new Timer(1000, new Ticker());
t.start();
JOptionPane.showMessageDialog(null, "Click OK to exit program");
System.exit(0);
}
class Ticker implements ActionListener {
private boolean tick = true;
public void actionPerformed(ActionEvent event) {
if (tick) {
System.out.println("Tick...");
} else {
System.out.println("Tock...");
}
tick = !tick;
}
}
}
Tick Tock with a Static Inner Class
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JOptionPane;
import javax.swing.Timer;
public class MainClass {
public static void main(String[] args) {
Timer t = new Timer(1000, new Ticker());
t.start();
JOptionPane.showMessageDialog(null, "Click OK to exit program");
System.exit(0);
}
static class Ticker implements ActionListener {
private boolean tick = true;
public void actionPerformed(ActionEvent event) {
if (tick) {
System.out.println("Tick...");
} else {
System.out.println("Tock...");
}
tick = !tick;
}
}
}
Timer: clock label
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class ClockTest extends JFrame {
public ClockTest() {
super("Timer Demo");
setSize(300, 100);
setDefaultCloseOperation(EXIT_ON_CLOSE);
ClockLabel clock = new ClockLabel();
getContentPane().add(clock, BorderLayout.NORTH);
}
public static void main(String args[]) {
ClockTest ct = new ClockTest();
ct.setVisible(true);
}
}
class ClockLabel extends JLabel implements ActionListener {
public ClockLabel() {
super("" + new Date());
Timer t = new Timer(1000, this);
t.start();
}
public void actionPerformed(ActionEvent ae) {
setText((new Date()).toString());
}
}
Time Resolution
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
/*
* TimeResolution.java
*
* Created on May 2, 2007, 3:38 PM
*
* Copyright (c) 2007, Sun Microsystems, Inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of the TimingFramework project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
*
* @author Chet
*/
public class TimeResolution implements ActionListener {
private static int INCREMENT = 5;
private static int MAX = 50;
/**
* Measures how much time has elapsed according to both currentTimeMillis()
* and nanoTime() at each interval. Note that the time reported for
* sleep() may not be accurate since the internal sleep timer may not
* have the appropriate resolution to sleep for the requested time.
* The main utility of this function is to compare the two timing
* functions, although it is also interesting to see how the measured
* time varies from the sleep() time.
*/
private void measureTimeFunctions(int increment, int max) {
long startTime = System.currentTimeMillis();
long startNanos = System.nanoTime();
long elapsedTimeActual = 0;
long elapsedTimeMeasured = 0;
long elapsedNanosMeasured = 0;
System.out.printf("sleep currentTimeMillis nanoTime\n");
while (elapsedTimeActual < max) {
try {
Thread.sleep(increment);
} catch (Exception e) {}
long currentTime = System.currentTimeMillis();
long currentNanos = System.nanoTime();
elapsedTimeActual += increment;
elapsedTimeMeasured = currentTime - startTime;
elapsedNanosMeasured = (currentNanos - startNanos) / 1000000;
System.out.printf(" %3d %4d %4d\n",
elapsedTimeActual, elapsedTimeMeasured, elapsedNanosMeasured);
}
}
/**
* This method measures the actual time slept, compared to the requested
* sleep() time. We run many iterations for each value of sleep() to
* get more accurate timing values; this accounts for possible
* inaccuracies of our nanoTime() method for small time differences.
*/
private void measureSleep() {
System.out.printf(" measured\n");
System.out.printf("sleep time iterations total time per-sleep\n");
for (int sleepTime = 0; sleepTime <= 20; ++sleepTime) {
int iterations = (sleepTime == 0) ? 10000 : (1000 / sleepTime);
long startTime = System.nanoTime();
for (int i = 0; i < iterations; ++i) {
try {
Thread.sleep(sleepTime);
} catch (Exception e) {
}
}
long endTime = System.nanoTime();
long totalTime = (endTime - startTime) / 1000000;
float calculatedSleepTime = totalTime / (float)iterations;
System.out.printf(" %2d %5d %4d %5.2f\n",
sleepTime, iterations, totalTime, calculatedSleepTime);
}
}
/**
* This method is like the measureSleep() method above, only for the
* wait() method instead of sleep().
*/
private synchronized void measureWait() {
System.out.printf(" measured\n");
System.out.printf("wait time iterations total time per-wait\n");
for (int sleepTime = 1; sleepTime <= 20; ++sleepTime) {
int iterations = (sleepTime == 0) ? 10000 : (1000 / sleepTime);
long startTime = System.nanoTime();
for (int i = 0; i < iterations; ++i) {
try {
wait(sleepTime);
} catch (Exception e) {
System.out.println("Exception: " + e);
Thread.dumpStack();
}
}
long endTime = System.nanoTime();
long totalTime = (endTime - startTime) / 1000000;
float calculatedSleepTime = totalTime / (float)iterations;
System.out.printf(" %2d %5d %4d %5.2f\n",
sleepTime, iterations, totalTime, calculatedSleepTime);
}
}
// Variables used in measurement of Swing timer
int timerIteration = 0;
int iterations = 0;
Timer timer;
long startTime, endTime;
int sleepTime;
/**
* This method is called during the execution of the Swing timer.
*/
public void actionPerformed(ActionEvent ae) {
if (++timerIteration > iterations) {
timer.stop();
timerIteration = 0;
endTime = System.nanoTime();
long totalTime = (endTime - startTime) / 1000000;
float calculatedDelayTime = totalTime / (float)iterations;
System.out.printf(" %2d %5d %5d %5.2f\n",
sleepTime, iterations, totalTime, calculatedDelayTime);
}
}
/**
* This method measures the accuracy of the Swing timer, which is
* internally dependent upon both the internal timing mechanisms
* (either currentTimeMillis() or nanoTime()) and the wait() method.
* So the results we see here should be predictable from the results
* we see in the other measurement methods.
*/
public void measureTimer() {
System.out.printf(" measured\n");
System.out.printf("timer delay iterations total time per-delay\n");
for (sleepTime = 0; sleepTime <= 20; ++sleepTime) {
iterations = (sleepTime == 0) ? 1000 : (1000 / sleepTime);
timerIteration = 1;
timer = new Timer(sleepTime, this);
startTime = System.nanoTime();
timer.start();
while (timerIteration > 0) {
try {
Thread.sleep(1000);
} catch (Exception e) {}
}
}
}
/**
* Execute the various timer resolution tests.
*/
public static void main(String args[]) {
TimeResolution timeResolution = new TimeResolution();
timeResolution.measureTimer();
timeResolution.measureTimeFunctions(INCREMENT, MAX);
timeResolution.measureSleep();
timeResolution.measureWait();
}
}
Timer Sample
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.Timer;
public class TimerSample {
public static void main(String args[]) {
new JFrame().setVisible(true);
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
System.out.println("Hello World Timer");
}
};
Timer timer = new Timer(500, actionListener);
timer.start();
}
}
Timer with ProgressBar
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class TimerExample extends JPanel implements ActionListener {
private Timer timer = new Timer(100, this);
private JLabel clockLabel;
private Calendar calendar = Calendar.getInstance();
private SimpleDateFormat dateFormat = new SimpleDateFormat("h:mm ss a");
private JProgressBar secondsProgressBar = new JProgressBar(0, 1000);
public TimerExample() {
this.clockLabel = new JLabel("Clock Stopped");
this.clockLabel.setFont(this.clockLabel.getFont().deriveFont(Font.BOLD, 16));
this.clockLabel.setHorizontalTextPosition(JLabel.CENTER);
this.secondsProgressBar.setVisible(false);
this.secondsProgressBar.setForeground(Color.blue);
add(this.clockLabel);
add(secondsProgressBar);
add(new JButton(new ToggleClockAction()));
}
private class ToggleClockAction extends AbstractAction {
private String startClock = "Start Clock";
private String stopClock = "Stop Clock";
private String clockStopped = "Clock Stopped";
public ToggleClockAction() {
super();
putValue(Action.NAME, startClock);
}
public void actionPerformed(ActionEvent e) {
if (TimerExample.this.timer.isRunning()) {
putValue(Action.NAME, startClock);
TimerExample.this.timer.stop();
TimerExample.this.secondsProgressBar.setVisible(false);
TimerExample.this.clockLabel.setText(clockStopped);
} else {
putValue(Action.NAME, stopClock);
// Call Action Performed To Initialize Time Before Timer is Started.
// Null is ok since we ignore the event.
TimerExample.this.actionPerformed(null);
TimerExample.this.secondsProgressBar.setVisible(true);
TimerExample.this.timer.start();
}
}
}
public void actionPerformed(ActionEvent e) {
this.calendar.setTimeInMillis(System.currentTimeMillis());
this.clockLabel.setText(this.dateFormat.format(this.calendar.getTime()));
int milliseconds = this.calendar.get(Calendar.MILLISECOND);
this.secondsProgressBar.setValue(milliseconds);
}
public void endExample() {
this.timer.stop();
}
public static void main(String[] a){
JFrame f = new JFrame();
f.setDefaultCloseOperation(1);
f.add(new TimerExample());
f.pack();
f.setVisible(true);
}
}