A New SwingWorker Example
Home ] Up ] Old SwingWorker ] An Old SwingWorker Example ] New SwingWorker ] [ A New SwingWorker Example ]

 

 

Here's an example of the use of the new (i.e. Java 6.0) SwingWorker class.

package swingWorker;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingWorker;

/**
 * Class to demonstrate the use of a SwingWorker thread.
 *
 */
public class SwingWorkerExample extends JFrame
{
  /**
   * Main entry point
   */
  public static void main(String[] args)
  {
    EventQueue.invokeLater( new Runnable()
      {
        public void run()
        {
          JFrame frame = new SwingWorkerExample();
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.pack();
          frame.setVisible(true);
        }
      }
    );
  }
  
  /**
   * Creates a new instance of SwingWorkerExample
   */
  public SwingWorkerExample()
  {
    Container panel = getContentPane();
    panel.setLayout( new BorderLayout() );
    panel.add( new InputPanel(), BorderLayout.NORTH );
    m_textArea.setRows(30);
    panel.add( new JScrollPane(m_textArea), BorderLayout.CENTER );
    panel.add( m_progressBar, BorderLayout.SOUTH );
    m_progressBar.setForeground(Color.RED);
    m_progressBar.setStringPainted(true);
  }
  
  //// Inner classes /////
  
  /**
   * Input panel to allow user to enter values, and start generation
   */
  private class InputPanel extends JPanel implements ActionListener
  {
    InputPanel()
    {
      add( new JLabel("Bits:") );
      add(m_bits);
      add( new JLabel("# of primes to generate:") );
      add(m_total);
      add(m_startButton);
      m_startButton.addActionListener(this);
      add(m_cancelButton);
      m_cancelButton.setEnabled(false);
      m_cancelButton.addActionListener( new ActionListener()
        {
          public void actionPerformed(ActionEvent event)
          {
            m_task.cancel(true);
          }
        }
      );
    }
    
    /**
     * Invoked on start button click
     */
    public void actionPerformed(ActionEvent e)
    {
      try
      {
        // Extract the input values
        // (Can generate NumberFormatExceptions)
        int bits = Integer.parseInt(m_bits.getText());
        int count = Integer.parseInt(m_total.getText());
        // Prevent multiple starts during work in progress
        m_startButton.setEnabled(false);
        // Allow for cancellation
        m_cancelButton.setEnabled(true);
        // Clear the text area
        m_textArea.setText("");
        // Create the worker task
        m_task = new PrimeNumbersTask(bits, count);
        // Set up to listen for progress changes
        m_task.addPropertyChangeListener( new PropertyChangeListener()
        {
          public  void propertyChange(PropertyChangeEvent evt)
          {
            if ("progress".equals(evt.getPropertyName()))
            {
              m_progressBar.setValue((Integer)evt.getNewValue());
            }
          }
        }
        );
        // Start the task thread
        m_task.execute();
      }
      catch (NumberFormatException nfe)
      {
        // No nothing (silently ignore the button click)
      }
    }
  }
  
  
  /**
   * Class to calculate a set of prime m_numbers in a worker thread.
   */
  private class PrimeNumbersTask extends SwingWorker< List<BigInteger>, BigInteger >
  {
    /**
     * Constructor.
     * @param bitCount the number of bits for a prime
     * @param primeCount the number of primes to generate
     */
    PrimeNumbersTask(int bitCount, int primeCount)
    {
      m_bitCount = bitCount;
      m_primeCount = primeCount;
    }
    
    /**
     * This method runs in the background, in the worker thread.
     */
    @Override
    public List<BigInteger> doInBackground()
    {
      while ( (m_numbers.size() < m_primeCount) && ! isCancelled())
      {
        BigInteger number = nextPrimeNumber();
        m_numbers.add(number);
        publish(number);
        setProgress(100 * m_numbers.size() / m_primeCount);
      }
      return m_numbers;
    }
    
    /**
     * Receives data chunks from the publish method
     * asynchronously on the Event Dispatch Thread.
     */
    @Override
    protected void process(List<BigInteger> chunks)
    {
      for (BigInteger number : chunks)
      {
        m_textArea.append(number + "\n");
      }
    }
    
    /**
     * Automatically invoked after the doBackground() method is finished.
     * This method runs in the context of the Event Dispatch Thread
     */
    @Override
    protected void done()
    {
      m_textArea.append("Generated total of " + m_numbers.size() +
        " primes of size " + m_bitCount + " bits.\n");
      // Reset state of buttons.
      m_startButton.setEnabled(true);
      m_cancelButton.setEnabled(false);
    }
    
    /**
     * Returns the next prime number
     */
    private BigInteger nextPrimeNumber()
    {
      return BigInteger.probablePrime(100, m_randomGenerator);
    }
    
    //// Private data ////
    private final int m_bitCount;
    private final int m_primeCount;
    private ArrayList<BigInteger> m_numbers = new ArrayList<BigInteger>();
    private Random m_randomGenerator = new Random(0);
  }
  
  //// Private data /////
  private JTextField m_bits = new JTextField(4);
  private JTextField m_total = new JTextField(4);
  private JButton m_startButton = new JButton("Start");
  private JButton m_cancelButton = new JButton("Cancel");
  private JTextArea m_textArea = new JTextArea();
  private final JProgressBar m_progressBar = new JProgressBar(0, 100);
  private PrimeNumbersTask m_task;
}

Try It!

Here is an applet that invokes the above code when you click on its "Start" button
(It requires the use of Java 6.0, so be prepared for errors if your browser plug-in is at a lower version number):

Your browser does not have Java support. Please install the Java Plug-in. After you've brought up the JFrame, click on the "Start" button, and see what actually happens! 

 

The page was last updated February 19, 2008