0

我正在创建一个简单的用户界面,用户可以单击一个按钮来运行特定的 Java 类。单击后,应向用户显示任务的进度,并为用户提供一个取消按钮,以在任务运行时的任何时间点终止任务。

在这种情况下,当用户单击 UI 中的 JButton 时,我将使用 ProgressMonitor 来显示,从而调用包含可运行线程的 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

4

1 回答 1

2

很可能,调用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 中的并发

于 2015-03-13T21:56:01.263 回答