【问题标题】:How to use jProgress bar for ProcessBuilder process?如何使用 ProcessBuilder 进程的进度条?
【发布时间】:2014-10-18 20:21:39
【问题描述】:

我正在开发一个 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 以及我必须在哪里使用?
谢谢

【问题讨论】:

  • 你需要在线程内执行cmd命令并使用中间进度条
  • 该命令给出什么输出?
  • 我很确定您不想在您尝试格式化的设备的根目录中执行该命令...
  • -1 用于发布有潜在危险的代码。版主已被标记。

标签: java swing netbeans process jprogressbar


【解决方案1】:

Swing 是单线程环境,它也不是线程安全的。

这意味着任何长时间运行或阻塞的进程都不应该在事件调度线程的上下文中运行,因为它会阻止它处理新事件,包括重绘请求,使程序看起来像挂起一样。

这也意味着你不应该从 EDT 的上下文之外创建或修改任何 UI 组件的状态。

更多详情请见Concurrency in Swing

您可以使用Thread 在其中运行流程,但您将负责确保您想要对 UI 进行的任何更改都在 EDT 的上下文中手动执行。这可能会变得很麻烦,尤其是当您想将信息从线程传递到 EDT 时。

另一个解决方案是使用SwingWorker,它提供的功能可以更轻松地在其后台线程和 EDT 之间同步数据。它支持通过setProgress 方法和PropertyListener 支持的进度通知,以及在EDT 上下文中从后台线程和process 获取publish 数据的能力。它还有一个不错的 done 方法,可以让您知道后台线程何时完成,但它是在 EDT 的上下文中执行的,例如...

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 并在done 方法中重置其状态,但这确实让它有点悬而未决,不知道工人何时真正开始,当然,你应该在调用worker之前设置状态,但是,管理UI的状态不是worker的责任

相反,您可以利用工作人员 PropertyChangeListener 的支持,例如...

    PropertyChangeListener listener = new PropertyChangeListener() {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            System.out.println(evt.getPropertyName() + "; " + evt.getNewValue());
            if ("state".equals(evt.getPropertyName())) {

                SwingWorker.StateValue state = (SwingWorker.StateValue) evt.getNewValue();
                switch (state) {
                    case DONE:
                        try {
                            int exitLevel = ((SwingWorker<Integer, ?>)evt.getSource()).get();
                            JOptionPane.showMessageDialog(null, "Format command completed with exit level of " + exitLevel);
                        } catch (InterruptedException | ExecutionException ex) {
                            JOptionPane.showMessageDialog(progressBar, ex.getMessage());
                        } finally {
                            progressBar.setIndeterminate(true);
                        }
                        break;
                    case STARTED:
                        progressBar.setIndeterminate(true);
                        break;
                }

            }
        }
    };
    FormatWorker worker = new FormatWorker("G");
    worker.addPropertyChangeListener(listener);
    worker.execute();

这使您可以决定如何响应工作人员,而无需将您与特定的工作流程联系起来。

Worker Threads and SwingWorker

【讨论】:

  • 这个答案很好。只是问你错过了 setIndeterminate(true) 还是不需要?
  • 因为进度条被传递给工作人员,我假设调用者设置了它。就个人而言,我更喜欢在 worker 上使用属性更改侦听器来监视完成状态并让调用者处理这一切,完全从 worker 移除任何 UI 责任,但我没时间了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-29
  • 2015-03-12
  • 2019-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多