Using a SwingWorker to display prime numbers and update a JProgressBar while the prime numbers are being calculated. - Java Swing

Java examples for Swing:Swing Thread

Description

Using a SwingWorker to display prime numbers and update a JProgressBar while the prime numbers are being calculated.

Demo Code

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;

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.ScrollPaneConstants;
import javax.swing.SwingWorker;

class PrimeCalculator extends SwingWorker<Integer, Integer> {
  private static final SecureRandom generator = new SecureRandom();
  private final JTextArea intermediateJTextArea; // displays found primes
  private final JButton getPrimesJButton;
  private final JButton cancelJButton;
  private final JLabel statusJLabel; // displays status of calculation
  private final boolean[] primes; // boolean array for finding primes

  // constructor//from  w w w . j av  a  2 s .  c o  m
  public PrimeCalculator(int max, JTextArea intermediateJTextArea,
      JLabel statusJLabel, JButton getPrimesJButton, JButton cancelJButton) {
    this.intermediateJTextArea = intermediateJTextArea;
    this.statusJLabel = statusJLabel;
    this.getPrimesJButton = getPrimesJButton;
    this.cancelJButton = cancelJButton;
    primes = new boolean[max];

    Arrays.fill(primes, true); // initialize all primes elements to true
  }

  public Integer doInBackground() {
    int count = 0; // the number of primes found
    for (int i = 2; i < primes.length; i++) {
      if (isCancelled()) // if calculation has been canceled
        return count;
      else {
        setProgress(100 * (i + 1) / primes.length);

        try {
          Thread.sleep(generator.nextInt(5));
        } catch (InterruptedException ex) {
          statusJLabel.setText("Worker thread interrupted");
          return count;
        }

        if (primes[i]) // i is prime
        {
          publish(i); // make i available for display in prime list
          ++count;

          for (int j = i + i; j < primes.length; j += i)
            primes[j] = false; // i is not prime
        }
      }
    }
    return count;
  }

  protected void process(List<Integer> publishedVals) {
    for (int i = 0; i < publishedVals.size(); i++)
      intermediateJTextArea.append(publishedVals.get(i) + "\n");
  }

  protected void done() {
    getPrimesJButton.setEnabled(true); // enable Get Primes button
    cancelJButton.setEnabled(false); // disable Cancel button

    try {
      statusJLabel.setText("Found " + get() + " primes.");
    } catch (InterruptedException | ExecutionException | CancellationException ex) {
      statusJLabel.setText(ex.getMessage());
    }
  }
}

public class Main extends JFrame {
  private final JTextField highestPrimeJTextField = new JTextField();
  private final JButton getPrimesJButton = new JButton("Get Primes");
  private final JTextArea displayPrimesJTextArea = new JTextArea();
  private final JButton cancelJButton = new JButton("Cancel");
  private final JProgressBar progressJProgressBar = new JProgressBar();
  private final JLabel statusJLabel = new JLabel();
  private PrimeCalculator calculator;

  public Main() {
    super("Finding Primes with SwingWorker");
    setLayout(new BorderLayout());
    JPanel northJPanel = new JPanel();
    northJPanel.add(new JLabel("Find primes less than: "));
    highestPrimeJTextField.setColumns(5);
    northJPanel.add(highestPrimeJTextField);
    getPrimesJButton.addActionListener(e -> {
      progressJProgressBar.setValue(0); // reset JProgressBar
        displayPrimesJTextArea.setText(""); // clear JTextArea
        statusJLabel.setText(""); // clear JLabel

        int number; // search for primes up through this value

        try {
          // get user input
          number = Integer.parseInt(highestPrimeJTextField.getText());
        } catch (NumberFormatException ex) {
          statusJLabel.setText("Enter an integer.");
          return;
        }
        calculator = new PrimeCalculator(number, displayPrimesJTextArea,
            statusJLabel, getPrimesJButton, cancelJButton);
        calculator.addPropertyChangeListener(e1 -> {
          if (e1.getPropertyName().equals("progress")) {
            int newValue = (Integer) e1.getNewValue();
            progressJProgressBar.setValue(newValue);
          }
        }

        );

        getPrimesJButton.setEnabled(false);
        cancelJButton.setEnabled(true);

        calculator.execute();
      }

      );
    northJPanel.add(getPrimesJButton);
    displayPrimesJTextArea.setEditable(false);
    add(new JScrollPane(displayPrimesJTextArea,
        ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
        ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER));

    JPanel southJPanel = new JPanel(new GridLayout(1, 3, 10, 10));
    cancelJButton.setEnabled(false);
    cancelJButton.addActionListener(e -> calculator.cancel(true));
    southJPanel.add(cancelJButton);
    progressJProgressBar.setStringPainted(true);
    southJPanel.add(progressJProgressBar);
    southJPanel.add(statusJLabel);

    add(northJPanel, BorderLayout.NORTH);
    add(southJPanel, BorderLayout.SOUTH);
    setSize(350, 300);
    setVisible(true);
  }

  public static void main(String[] args) {
    Main application = new Main();
    application.setDefaultCloseOperation(EXIT_ON_CLOSE);
  }
}

Related Tutorials