[英]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.