All pastes #576283 Raw Edit

Someone

public text v1 · immutable
·published 2007-06-19 12:38 UTC
rendered paste body
package javaexample.swing.progressbar;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class ProgressMonitorDemo
    extends JFrame {

  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;

  public ProgressMonitorDemo() {
    super("ProgressMonitorDemo");
    newline = System.getProperty("line.separator");

    task = new LongTask();

    //create the demo's UI
    startButton = new JButton("Start");
    startButton.setActionCommand("start");
    startButton.addActionListener(new ButtonListener());

    taskOutput = new JTextArea(5, 20);
    taskOutput.setMargin(new Insets(5, 5, 5, 5));
    taskOutput.setEditable(false);

    JPanel contentPane = new JPanel();
    contentPane.setLayout(new BorderLayout());
    contentPane.add(startButton, BorderLayout.NORTH);
    contentPane.add(new JScrollPane(taskOutput), BorderLayout.CENTER);
    contentPane.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
    setContentPane(contentPane);

    //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) {
      if (progressMonitor.isCanceled() || task.done()) {
        progressMonitor.close();
        task.stop();
        Toolkit.getDefaultToolkit().beep();
        timer.stop();
        startButton.setEnabled(true);
      }
      else {
        progressMonitor.setNote(task.getMessage());
        progressMonitor.setProgress(task.getCurrent());
        taskOutput.append(task.getMessage() + newline);
        taskOutput.setCaretPosition(taskOutput.getDocument().getLength());
      }
    }
  }

  //the actionPerformed method in this class
  //is called when the user presses the start button
  class ButtonListener
      implements ActionListener {
    public void actionPerformed(ActionEvent evt) {
      progressMonitor = new ProgressMonitor(ProgressMonitorDemo.this,
                                            "Running a Long Task",
                                            "", 0, task.getLengthOfTask());
      progressMonitor.setProgress(0);
      progressMonitor.setMillisToDecideToPopup(2 * ONE_SECOND);

      startButton.setEnabled(false);
      task.go();
      timer.start();
    }
  }

  public static void main(String[] args) {

    JFrame frame = new ProgressMonitorDemo();

    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });

    frame.pack();
    frame.setVisible(true);
  }
}


// LongTask.java

package javaexample.swing.progressbar;

class LongTask {
  private int lengthOfTask;
  private int current = 0;
  private String statMessage;

  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
  void go() {
    current = 0;
    final SwingWorker worker = new SwingWorker() {
      public Object construct() {
        return new ActualTask();
      }
    };
  }

  //called from ProgressBarDemo to find out how much work needs to be done
  int getLengthOfTask() {
    return lengthOfTask;
  }

  //called from ProgressBarDemo to find out how much has been done
  int getCurrent() {
    return current;
  }

  void stop() {
    current = lengthOfTask;
  }

  //called from ProgressBarDemo to find out if the task has completed
  boolean done() {
    if (current >= lengthOfTask) {
      return true;
    }
    else {
      return false;
    }
  }

  String getMessage() {
    return statMessage;
  }

  //the actual long running task, this runs in a SwingWorker thread
  class ActualTask {
    ActualTask() {
      //fake a long task,
      //make a random amount of progress every second
      while (current < lengthOfTask) {
        try {
          Thread.sleep(1000); //sleep for a second
          current += Math.random() * 100; //make some progress
          statMessage = "Completed " + current +
              " out of " + lengthOfTask + ".";
        }
        catch (InterruptedException e) {
        }
      }
    }
  }
}


// SwingWorker.java

package javaexample.swing.progressbar;

//import com.sun.java.swing.SwingUtilities;  //old package name
import javax.swing.SwingUtilities; //new package name

/**
 * An abstract class that you subclass to perform
 * GUI-related work in a dedicated thread.
 * For instructions on using this class, see
 * http://java.sun.com/products/jfc/swingdoc-current/threads2.html
 */
public abstract class SwingWorker {
  private Object value; // see getValue(), setValue()
  private Thread thread;

  /**
   * 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 abort 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);
    t.start();
  }
}