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;
}
|