我正在开发一个java应用程序,通过ProcessBuilder执行CMD命令,使usb驱动器可启动。这需要几秒钟,因为我想显示一个jprogressbar来增加GUI,我已经尝试过,我没有,请帮助我。
这是我的代码:
private void btn_StartActionPerformed(java.awt.event.ActionEvent evt)
{
String[] command ={"CMD", "/C", "MyCmdCommand"};
ProcessBuilder probuilder = new ProcessBuilder( command );
probuilder.directory(new File(dri+":\\"));
try
{
Process process = probuilder.start();
process.waitFor();
}
catch(IOException e)
{
JOptionPane.showMessageDialog(this, e);
}
}
我如何在我的代码中使用JProgressbar以及我必须使用的地方? 谢谢
答案 0 :(得分:2)
Swing是一个单线程环境,它也不是线程安全的。
这意味着任何长时间运行或阻塞进程都不应该在事件调度线程的上下文中运行,因为它会阻止它处理新事件,包括重绘请求,使程序看起来像挂起
这也意味着你永远不应该在EDT的上下文之外创建或修改任何UI组件的状态。
有关详细信息,请参阅Concurrency in Swing。
您可以使用Thread
在其中运行该过程,但您将负责确保您要对UI进行的任何更改都是在EDT的上下文中手动执行的。这可能会变得很麻烦,尤其是当您想要将信息从线程传递到EDT时。
另一个解决方案是使用SwingWorker
,它提供的功能可以更容易地在它的后台线程和EDT之间同步数据。它支持通过setProgress
方法和PropertyListener
支持的进度通知,以及在EDT上下文中来自后台线程和publish
的{{1}}数据的功能。它还有一个很好的process
方法,可以让你知道后台线程何时完成,但是在EDT的上下文中执行,例如......
done
现在,您可能想要将public static class FormatWorker extends SwingWorker<Integer, Integer> {
private String drive;
public FormatWorker(String drive) {
this.drive = drive;
}
@Override
protected Integer doInBackground() throws Exception {
String[] command = {"CMD", "/C", "MyCmdCommand"};
ProcessBuilder probuilder = new ProcessBuilder(command);
probuilder.directory(new File(drive + ":\\"));
Process process = probuilder.start();
return process.waitFor();
return 0;
}
}
传递给JProgressBar
并在SwingWorker
方法中重置其状态,但这确实会让它暂停一点,不知道当工人真正开始工作时,当然,你应该在调用工人之前设置状态,但是,管理UI的状态不是工人的责任
相反,您可以利用工作人员done
支持,例如......
PropertyChangeListener
这使您可以决定如何响应工作人员,而无需将您与特定的工作流程联系起来。