We would like to know how to start and cancel a lengthy task.
/*from www. j av a 2 s.c o m*/ /* From http://java.sun.com/docs/books/tutorial/index.html */ /* * Copyright (c) 2006 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: * * -Redistribution of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution 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 Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. */ import java.awt.*; import java.awt.event.*; import javax.swing.*; /* * ProgressMonitorDemo.java is a 1.4 application that requires these files: * LongTask.java * SwingWorker.java */ public class Main extends JPanel implements ActionListener { public final static int ONE_SECOND = 1000; private ProgressMonitor progressMonitor; private Timer timer; private JButton startButton; private LongTask task; private JTextArea taskOutput; private String newline = "\n"; public Main() { super(new BorderLayout()); task = new LongTask(); //Create the demo's UI. startButton = new JButton("Start"); startButton.setActionCommand("start"); startButton.addActionListener(this); taskOutput = new JTextArea(5, 20); taskOutput.setMargin(new Insets(5,5,5,5)); taskOutput.setEditable(false); add(startButton, BorderLayout.PAGE_START); add(new JScrollPane(taskOutput), BorderLayout.CENTER); setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); //Create a timer. timer = new Timer(ONE_SECOND, new TimerListener()); } /** * The actionPerformed method in this class * is called each time the Timer "goes off". */ class TimerListener implements ActionListener { public void actionPerformed(ActionEvent evt) { progressMonitor.setProgress(task.getCurrent()); String s = task.getMessage(); if (s != null) { progressMonitor.setNote(s); taskOutput.append(s + newline); taskOutput.setCaretPosition( taskOutput.getDocument().getLength()); } if (progressMonitor.isCanceled() || task.isDone()) { progressMonitor.close(); task.stop(); Toolkit.getDefaultToolkit().beep(); timer.stop(); if (task.isDone()) { taskOutput.append("Task completed." + newline); } else { taskOutput.append("Task canceled." + newline); } startButton.setEnabled(true); } } } /** * Called when the user presses the start button. */ public void actionPerformed(ActionEvent evt) { progressMonitor = new ProgressMonitor(Main.this, "Running a Long Task", "", 0, task.getLengthOfTask()); progressMonitor.setProgress(0); progressMonitor.setMillisToDecideToPopup(2 * ONE_SECOND); startButton.setEnabled(false); task.go(); timer.start(); } /** * Create the GUI and show it. For thread safety, * this method should be invoked from the * event-dispatching thread. */ private static void createAndShowGUI() { //Make sure we have nice window decorations. JFrame.setDefaultLookAndFeelDecorated(true); //Create and set up the window. JFrame frame = new JFrame("ProgressMonitorDemo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Create and set up the content pane. JComponent newContentPane = new Main(); newContentPane.setOpaque(true); //content panes must be opaque frame.setContentPane(newContentPane); //Display the window. frame.pack(); frame.setVisible(true); } public static void main(String[] args) { //Schedule a job for the event-dispatching thread: //creating and showing this application's GUI. javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } } /** * This is the 3rd version of SwingWorker (also known as * SwingWorker 3), an abstract class that you subclass to * perform GUI-related work in a dedicated thread. For * instructions on and examples of using this class, see: * * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html * * Note that the API changed slightly in the 3rd version: * You must now invoke start() on the SwingWorker after * creating it. */ abstract class SwingWorker { private Object value; // see getValue(), setValue() /** * Class to maintain reference to current worker thread * under separate synchronization control. */ private static class ThreadVar { private Thread thread; ThreadVar(Thread t) { thread = t; } synchronized Thread get() { return thread; } synchronized void clear() { thread = null; } } private ThreadVar threadVar; /** * Get the value produced by the worker thread, or null if it * hasn't been constructed yet. */ protected synchronized Object getValue() { return value; } /** * Set the value produced by worker thread */ private synchronized void setValue(Object x) { value = x; } /** * Compute the value to be returned by the <code>get</code> method. */ public abstract Object construct(); /** * Called on the event dispatching thread (not on the worker thread) * after the <code>construct</code> method has returned. */ public void finished() { } /** * A new method that interrupts the worker thread. Call this method * to force the worker to stop what it's doing. */ public void interrupt() { Thread t = threadVar.get(); if (t != null) { t.interrupt(); } threadVar.clear(); } /** * Return the value created by the <code>construct</code> method. * Returns null if either the constructing thread or the current * thread was interrupted before a value was produced. * * @return the value created by the <code>construct</code> method */ public Object get() { while (true) { Thread t = threadVar.get(); if (t == null) { return getValue(); } try { t.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // propagate return null; } } } /** * Start a thread that will call the <code>construct</code> method * and then exit. */ public SwingWorker() { final Runnable doFinished = new Runnable() { public void run() { finished(); } }; Runnable doConstruct = new Runnable() { public void run() { try { setValue(construct()); } finally { threadVar.clear(); } SwingUtilities.invokeLater(doFinished); } }; Thread t = new Thread(doConstruct); threadVar = new ThreadVar(t); } /** * Start the worker thread. */ public void start() { Thread t = threadVar.get(); if (t != null) { t.start(); } } } class LongTask { private int lengthOfTask; private int current = 0; private boolean done = false; private boolean canceled = false; private String statMessage; public LongTask() { //Compute length of task... //In a real program, this would figure out //the number of bytes to read or whatever. lengthOfTask = 1000; } /** * Called from ProgressBarDemo to start the task. */ public void go() { final SwingWorker worker = new SwingWorker() { public Object construct() { current = 0; done = false; canceled = false; statMessage = null; return new ActualTask(); } }; worker.start(); } /** * Called from ProgressBarDemo to find out how much work needs * to be done. */ public int getLengthOfTask() { return lengthOfTask; } /** * Called from ProgressBarDemo to find out how much has been done. */ public int getCurrent() { return current; } public void stop() { canceled = true; statMessage = null; } /** * Called from ProgressBarDemo to find out if the task has completed. */ public boolean isDone() { return done; } /** * Returns the most recent status message, or null * if there is no current status message. */ public String getMessage() { return statMessage; } /** * The actual long running task. This runs in a SwingWorker thread. */ class ActualTask { ActualTask() { //Fake a long task, //making a random amount of progress every second. while (!canceled && !done) { try { Thread.sleep(1000); //sleep for a second current += Math.random() * 100; //make some progress if (current >= lengthOfTask) { done = true; current = lengthOfTask; } statMessage = "Completed " + current + " out of " + lengthOfTask + "."; } catch (InterruptedException e) { System.out.println("ActualTask interrupted"); } } } } }