[英]Send Parameter To Runtime.getRuntime().exec() After Execution
[英]Swing message doesn't get displayed until after Runtime.getRuntime().exec() finishes execution
我是Swing的新手。 我试图创建一个摆动包装器,以允许用户浏览和选择文件夹,并且该文件夹路径用作控制台.exe程序的命令行参数。 他们选择文件夹并单击“启动程序”按钮后,我希望旋转窗口显示一条消息,告诉他们该程序正在处理(并显示时钟的gif动画),运行外部程序,然后显示另一条消息该程序完成执行时。 我遇到的问题是,直到外部程序完成执行后,才会显示“正在处理”消息。 在下面的代码中,单击“启动程序”按钮时,将执行onLaunchProgram方法。 我尝试过revalidate()和repaint(),但没有任何变化。 我有一个“已完成”消息的waitFor(),但是即使取出该消息,也不会显示“正在处理”消息和gif,直到外部程序完成执行。
...
JTextField txtFolder = new JTextField();
JLabel lblMessage = new JLabel();
JLabel lblPic = new JLabel();
JButton btnLaunchApplication = new JButton("Launch Program");
...
btnLaunchApplication.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
onLaunchProgram(evt);
}
});
...
if (returnVal == JFileChooser.APPROVE_OPTION){
file = fc.getSelectedFile();
txtFolder.setText(file.getAbsolutePath());
}
...
private void onLaunchProgram(ActionEvent evt) {
String strExecutableFilename = "MyExecutableProgam";
String strSourceFolder = txtFolder.getText();
String strCommand = strExecutableFilename + " " + strSourceFolder;
lblMessage.setText("Processing");
ImageIcon icon = new ImageIcon("clock.gif");
lblPic.setIcon(icon);
try {
Process procCommand = Runtime.getRuntime().exec(strCommand);
try {
procCommand.waitFor();
} catch (InterruptedException exception) {
exception.printStackTrace();
} finally {
}
lblMessage.setText("Finished");
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
从示例代码很难确定如何执行onLaunchProgram
方法,但是从您的描述来看,假设您是在事件调度线程的上下文中执行它是一个onLaunchProgram
选择。
事件分派线程负责(除其他事项外)分派重画请求。 阻止此线程的任何事情都将阻止它更新UI。
由于procCommand.waitFor()
是阻止操作,因此将阻止处理任何重画请求(或与此事件有关的任何事件),直到返回为止。
您应该在单独的线程中执行所有耗时或阻塞的过程。 但是,您遇到的问题是,对UI桅杆的所有更新都是在EDT的上下文中执行的(也就是说,您不应从EDT之外的任何线程更改/更新/修改/创建任何UI组件)
在Swing中,您有很多选择,我建议您使用SwingWorker
。 它将允许您在后台线程中执行该过程,但具有一些易于使用的方法来将更新重新同步到UI。
public class ProcessWorker extends SwingWorker<Integer, String> {
private String program;
private String sourceFolder;
public ProcessWorker(String program, String sourceFolder) {
this.program = program;
this.sourceFolder = sourceFolder;
}
@Override
protected void process(List<String> 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
工作时遇到的一些困难。
您应该查看http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html了解更多详细信息
似乎您正在一个线程中完成所有操作。
使用事件分配线程来调用您的gui代码。
private void onLaunchProgram(ActionEvent evt) {
String strExecutableFilename = "MyExecutableProgam";
String strSourceFolder = txtFolder.getText();
String strCommand = strExecutableFilename + " " + strSourceFolder;
ImageIcon icon = new ImageIcon("clock.gif");
javax.swing.SwingUtilities.invokeLater(
new Runnable() {
public void run() {
lblMessage.setText("Processing");
lblPic.setIcon(icon);
}
});
try {
Process procCommand = Runtime.getRuntime().exec(strCommand);
try {
procCommand.waitFor();
} catch (InterruptedException exception) {
exception.printStackTrace();
} finally {
}
javax.swing.SwingUtilities.invokeLater(
new Runnable() {
public void run() {
lblMessage.setText("Finished");
}
});
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.