您的示例代码很难确定如何执行onLaunchProgram方法,但是从您的描述中,假设您在事件调度线程的上下文中执行它将是一个安全的节拍.
Event Dispatching Thread负责(除其他事项外)调度重绘请求.阻止此线程的任何事情都会阻止它更新UI.
因为procCommand.waitFor()是一个阻塞操作,所以这将阻止任何重绘请求(或任何事件)在返回之前被处理.
您应该在单独的线程中执行所有耗时或阻塞进程.但是你遇到的问题是,所有对UI的更新都要在EDT的上下文中执行(也就是说,你永远不应该从EDT以外的任何线程更改/更新/修改/创建任何UI组件)
在Swing中你有很多选择,在你的情况下,我建议使用SwingWorker.它允许您在后台线程中执行该过程,但有一些易于使用的方法来重新同步UI的更新.
public class ProcessWorker extends SwingWorker {
private String program;
private String sourceFolder;
public ProcessWorker(String program, String sourceFolder) {
this.program = program;
this.sourceFolder = sourceFolder;
}
@Override
protected void process(List chunks) {
// Back on the EDT
for (String value : chunks) {
if (value.equalsIgnoreCase("PROCESSING")) {
lblMessage.setText("Processing");
ImageIcon icon = new ImageIcon("clock.gif");
lblPic.setIcon(icon);
} else if (value.equalsIgnoreCase("FINISHED")) {
lblMessage.setText("Finished");
} else {
// Possible some other message...
}
}
}
@Override
protected Integer doInBackground() throws Exception {
int result = -1;
String strExecutableFilename = program;
String strSourceFolder = sourceFolder;
String strCommand = strExecutableFilename + " " + strSourceFolder;
publish("PROCESSING");
// lblMessage.setText("Processing");
// ImageIcon icon = new ImageIcon("clock.gif");
// lblPic.setIcon(icon);
try {
ProcessBuilder pb = new ProcessBuilder(program);
pb.redirectError();
pb.directory(new File(strSourceFolder));
Process procCommand = pb.start();
// Process procCommand = Runtime.getRuntime().exec(strCommand);
try {
result = procCommand.waitFor();
} catch (InterruptedException exception) {
exception.printStackTrace();
} finally {
}
// lblMessage.setText("Finished");
publish("FINISHED");
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
您还应该熟悉ProcessBuilder.它有许多有用的构建过程的方法,并克服了人们在尝试使Runtime.getRuntime().exec工作时遇到的一些困难.