Progressmonitor does not show up in JavaSwing

555 views Asked by At

I am creating a simple user interface whereby a user could click on a button to run a specific Java class. Upon clicking, the progress of the task should be displayed to the user and also provide a Cancel button for the user to terminate the task at any point of time while the task is running.

In this case, I am using a ProgressMonitor to be displayed when a user clicks on a JButton in the UI, whereby runEngineerBuild() containing a runnable thread will be invoked to execute the methods of another Java class (called EngineerBuild.java). However, the ProgressMonitor dialog does not display. How can I get the ProgressDialog to show? I'm wondering if it is because of the nature of multiple running threads or maybe I'm missing out on something. Would really appreciate your help!

In SecondPanel.java:

package mainApplication;

import java.awt.Font;

public class SecondPanel extends JPanel {
 private MainApplication ma = null;  // main JFrame

 private JPanel pnlBtn;
 private JPanel pnlProgress;

 private JButton btnRunAll;
 private JButton btnEngBuild;
 private JButton btnWholeDoc;
 private JButton btnCancelProgress;

 private JLabel lblTitleSteps;
 private JLabel lblAlt;
 private JLabel lbl_1a;
 private JLabel lbl_1b_c;
 private JLabel lblTitleStatus;

 private JProgressBar progressRunAll;
 private JProgressBar progressEngBuild;
 private JProgressBar progressWholeDoc;

 private Property property = Property.getInstance();
 // private Task task;
 private boolean cancelFlag;

 /**
  * Create the panel for Step 1 TabbedPane.
  */

 public SecondPanel(MainApplication mainApp) {
  // TODO Auto-generated constructor stub
  super();
  ma = mainApp;
 }

 public SecondPanel() {
  this.setBackground(new Color(224, 255, 255));
  this.setBounds(0, 0, 745, 1350);
  this.setPreferredSize(new Dimension(745, 600));
  this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));

  pnlBtn = new JPanel();
  pnlBtn.setLayout(new BoxLayout(pnlBtn, BoxLayout.PAGE_AXIS));
  pnlBtn.setAlignmentY(Component.TOP_ALIGNMENT);

  pnlProgress = new JPanel();
  pnlProgress.setLayout(new BoxLayout(pnlProgress, BoxLayout.PAGE_AXIS));
  pnlProgress.setAlignmentY(TOP_ALIGNMENT);

  pnlBtn.add(Box.createRigidArea(new Dimension(0, 15)));

  btnEngBuild = new JButton("Run EngineerBuild.java");
  btnEngBuild.setToolTipText("Build search engineer");
  btnEngBuild.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent event) {
    // start activity
    activity = new SimulatedActivity(1000);
    activity.start();

    // launch progress dialog
    progressDialog = new ProgressMonitor(ma,
      "Waiting for Simulated Activity", null, 0, activity
        .getTarget());
    progressDialog.setMillisToPopup(1000);

    // start timer
    activityMonitor = new Timer(500, null);
    activityMonitor.start();

    btnEngBuild.setEnabled(false);
   }
  });

  activityMonitor = new Timer(500, new ActionListener() {
   private PrintStream textArea;

   public void actionPerformed(ActionEvent event) {
    int current = activity.getCurrent();

    // show progress
    runEngineerBuild();
    textArea.append(current + "\n");
    progressDialog.setProgress(current);

    // check if task is completed or canceled
    if (current == activity.getTarget() || progressDialog.isCanceled()) {
     activityMonitor.stop();
     progressDialog.close();
     activity.interrupt();
     btnEngBuild.setEnabled(true);
    }
   }
  });

  btnEngBuild.setMinimumSize(new Dimension(200, 30));
  btnEngBuild.setPreferredSize(new Dimension(200, 30));
  btnEngBuild.setMaximumSize(new Dimension(200, 30));
  pnlBtn.add(btnEngBuild);

  pnlBtn.add(Box.createRigidArea(new Dimension(0, 15)));

  // components in panel progress
  lblTitleStatus = new JLabel();
  lblTitleStatus.setText("<html><u>Task Status</u></html>");

  progressEngBuild = new JProgressBar();
  Border border2 = BorderFactory.createTitledBorder("Run EngineerBuild");
  progressEngBuild.setBorder(border2);

  // title
  pnlProgress.add(lblTitleStatus);
  pnlProgress.add(Box.createRigidArea(new Dimension(0, 15)));
  pnlProgress.add(progressEngBuild);
  pnlProgress.add(Box.createRigidArea(new Dimension(0, 15)));
  
  this.add(Box.createRigidArea(new Dimension(15, 10)));
  this.add(pnlBtn);
  this.add(Box.createRigidArea(new Dimension(50, 10)));
  this.add(pnlProgress);
 }

 public void runEngineerBuild() 
 {
  EngineerBuildRunnable ebr = new EngineerBuildRunnable();
  ebr.run();

 }
 private class EngineerBuildRunnable implements Runnable {
  EngineerBuild eb;

  public EngineerBuildRunnable() {
   eb = new EngineerBuild();
  }

  public void run() {
   eb.initial();
   eb.storeIntoFile();
  }
 }

 private Timer activityMonitor;
 private ProgressMonitor progressDialog;
 private SimulatedActivity activity;

 public static final int WIDTH = 300;
 public static final int HEIGHT = 200;
}

/**
 * A simulated activity thread.
 */
class SimulatedActivity extends Thread {
 /**
  * Constructs the simulated activity thread object. The thread increments a
  * counter from 0 to a given target.
  * 
  * @param t
  *            the target value of the counter.
  */
 public SimulatedActivity(int t) {
  current = 0;
  target = t;
 }

 public int getTarget() {
  return target;
 }

 public int getCurrent() {
  return current;
 }

 public void run() {
  try {
   while (current < target && !interrupted()) {
    sleep(100);
    current++;
   }
  } catch (InterruptedException e) {
  }
 }

 private int current;
 private int target;
}

Here's the link for the original ProgressMonitor code if you're interested:

User Interface Programming - Example 1-11 ProgressMonitorTest.java

1

There are 1 answers

1
Hovercraft Full Of Eels On

In all likelihood, calling runEngineerBuild() will call long-running code, something that you're doing on the Swing event thread, and this will tie up the thread rendering your GUI useless and frozen until that long-running code has completed its run. The solution is the same as all similar issues -- call runEngineerBuild() in a background thread such as a SwingWorker.

A quick fix would be to explicitly call runEngineerBuild() in a simple thread:

EngineerBuildRunnable ebr = new EngineerBuildRunnable();
new  Thread(ebr).start();
// ebr.run(); // !!! don't call a Runnable's run method directly !!!!

For details on how to use a SwingWorker, please check out: Lesson: Concurrency in Swing.