Progressmonitor не отображается в JavaSwing

Я создаю простой пользовательский интерфейс, в котором пользователь может нажать на кнопку, чтобы запустить определенный класс Java. При нажатии пользователь должен отобразить ход выполнения задачи, а также предоставить кнопку "Отмена", чтобы пользователь мог завершить задачу в любой момент времени во время ее выполнения.

В этом случае я использую ProgressMonitor, который будет отображаться, когда пользователь щелкает JButton в пользовательском интерфейсе, в результате чего запускается runEngineerBuild(), содержащая выполняемый поток, для выполнения методов другого Java-класса (называемого EngineerBuild.java). Однако диалоговое окно ProgressMonitor не отображается. Как я могу получить ProgressDialog, чтобы показать? Мне интересно, если это из-за природы нескольких запущенных потоков или, может быть, я что-то упускаю. Буду очень признателен за вашу помощь!

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

Вот ссылка на оригинальный код ProgressMonitor, если вы заинтересованы:

Программирование пользовательского интерфейса - пример 1-11 ProgressMonitorTest.java

1 ответ

По всей вероятности, звонит runEngineerBuild() вызовет долгосрочный код, что вы делаете в потоке событий Swing, и это свяжет поток, делая ваш GUI бесполезным и замороженным, пока этот долгосрочный код не завершит свой запуск. Решение такое же, как и у всех аналогичных вопросов - звоните runEngineerBuild() в фоновом потоке, таком как SwingWorker.

Быстрое решение проблемы - явный вызов runEngineerBuild() в простой теме:

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

Для получения подробной информации о том, как использовать SwingWorker, пожалуйста, прочитайте: Урок: Параллельность в Swing.

Другие вопросы по тегам