2

I am executing an external process at the backend using Processbuilder in my java program.I am using process.waitFor to get the exit status of the process. The backend process 'll take time which depends upon the input provided.so i need to make a progressbar for indeterminate time until the process completes. This is just to notify the user that there is a process going on at back end.

    try {
        button.setEnabled(false);
        this.progressbar.setVisible(true);
        this.progressbar.setIndeterminate(true);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        perform(this);
    }
}                                    

public void perform(JFrame f)
{
            String cmd[]={"cmd", "/c","a.exe:};
            ProcessBuilder pb = new ProcessBuilder(cmd);
            pb.directory(new File(dir_path));
            pb.redirectErrorStream(true);
            try {
                    p = pb.start();
                } catch (IOException ex) {
                    Logger.getLogger(execution.class.getName()).log(Level.SEVERE, null, ex);
                       }
            try
            {
               int exitVal = p.waitFor();
               if(exitVal>0)
               {
                   this.progressbar.setVisible(false);
                   this.progressbar.setIndeterminate(false);
                   this.button.setEnabled(true);
               }
               if(p.waitFor()==0)
               {
                   this.progressbar.setVisible(false);
                   this.progressbar.setIndeterminate(false);

                   JOptionPane.showMessageDialog(f,"Scan completed successfully.");
               }
             } catch (InterruptedException ex) {
    Logger.getLogger(execution.class.getName()).log(Level.SEVERE, null, ex);
}
}

Button is the name of my button which invokes the call. But the problem I'm facing is the function call perform is made without executing these statements.

    try {
        button.setEnabled(false);
        this.progressbar.setVisible(true);
        this.progressbar.setIndeterminate(true);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

Button is disabled after the execution of that function. 1) may i know why that happens? 2) may i know the solution to make progressbar indicating the backend progress until it completes?

Thanks in advance.

4

2 回答 2

2

我建议使用SwingWorker. 它是为诸如此类的问题而设计的。这是我的代码库中一些代码的片段(vui是一个 JFrame):

vui.clearOutput();
vui.setOutput("Waiting for items to copy...\n"
            + "This could take several minutes. Please standby...");
vui.disableExit();
vui.disableInput();
vui.disableNext();
vui.showProgressBar();

// make thread so you can disable all options when zipping and enable progress bar
SwingWorker transferWorker = new SwingWorker() {
    @Override
    protected Void doInBackground() throws Exception {
        try {
            Process p = Runtime.getRuntime().exec("resources/bin/transferCopier.bat");

            StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(), "ERROR");
            StreamGobbler outputGobbler = new StreamGobbler(p.getInputStream(), "OUTPUT");
            errorGobbler.start();
            outputGobbler.start();

            p.waitFor();
        } catch (IOException ex) {
            Logger.getLogger(VaderController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InterruptedException ie) {
            Logger.getLogger(VaderController.class.getName()).log(Level.SEVERE, null, ie);
        }
        return null;
    }
    @Override
    public void done() {
        vui.hideProgressBar();
        vui.clearOutput();
        vui.setOutput("Transfer Complete!\n\n"
                    + "Push \"Exit\" to quit.\n\n");
        vui.enableExit();
        mode = VaderMode.END;
    }
};
transferWorker.execute();

transferWorker.execute();被执行时,doInBackground()被调用。一旦doInBackground()完成计算,done()然后调用。done()是您对 GUI 进行任何最终更新的地方。

关于我上面的代码要注意的关键事项是,我在执行之前启用了进度条,SwingWorker然后当SwingWorker完成执行时,我禁用了进度条。

资源:

http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html

于 2013-04-09T12:29:25.387 回答
0

它被执行,但它与 GUI 在同一个线程中执行,因此视图不会更新。

在显示 ProgressBar 并禁用 Button 后,启动一个等待进程完成的可运行文件。

简单地包装perform()在一个 Runnable 中。

未经测试的代码:而不是perform(this)你写:

new Thread(new Runnable() { 
    public void run() {
        perform(YourClassName.this);
    }
}).start();
于 2013-04-09T12:25:22.823 回答