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.