2013-04-09 22 views
2

我在後端使用Processbuilder在我的Java程序中執行外部進程。我使用process.waitFor來獲取進程的退出狀態。後端進程將需要時間,這取決於所提供的輸入。因此,我需要在進程完成之前爲進程條創建一個不確定的時間。這只是爲了通知用戶後端正在進行一個過程。進度顯示器(不確定)顯示執行發生在後端

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); 
} 
} 

按鈕是調用該調用的按鈕的名稱。但是,我面臨的問題是函數調用執行,而不執行這些語句。

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

按鈕是函數的執行後被禁止。 1)我可以知道爲什麼會發生? 2)我可以知道解決方案使進度條指示後端進度,直到它完成嗎?

在此先感謝。

+0

我想也許嘗試重構這一點,所以它的使用'SwingWorker' – Franklin 2013-04-09 12:21:46

回答

0

它被執行,但它在與GUI相同的線程中執行,所以視圖不會被更新。

顯示ProgressBar並禁用Button後,啓動一個等待Process完成的runnable。

只需將perform()包裝在Runnable中即可。

未經測試的代碼:的 代替perform(this)你寫:

new Thread(new Runnable() { 
    public void run() { 
     perform(YourClassName.this); 
    } 
}).start(); 
+0

好感謝。會嘗試。 – sreram 2013-04-09 12:27:36

+0

現在能夠獲得進度監視器,但控件不會進入該功能(執行)。 – sreram 2013-04-09 12:54:04

+0

你是否開始()線程?我編輯了我的答案,包括一個未經測試的例子,我將如何嘗試這樣做。 – MaPePeR 2013-04-09 12:59:16

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