2011-10-03 27 views
3

我已爲Eclipse插件實施了一個嚮導,顯示了多個頁面。其中一個頁面需要一些冗長的初始化,這意味着它包含一個SWT表,它需要由來自外部源的信息填充。此源需要先激活(在幾秒鐘後返回一個單一的方法調用 - 我無法預先知道需要多久),然後才能將其用作表查看器的輸入。這個初始化當前是由表模型提供者在需要第一次訪問外部源時完成的。如何在Eclipse嚮導中正確更新未知持續時間操作的進度條?

因此,當我進入嚮導頁面時,我想顯示一個虛擬的進度條,只是計數一段時間。我的做法是下面的,但遺憾的是沒有在所有的工作:

private void initViewer() { 
    IRunnableWithProgress runnable = new IRunnableWithProgress() { // needed to embed long running operation into the wizard page 

     @Override 
     public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { 
      SubMonitor progress = SubMonitor.convert(monitor); 

      Thread thread = new Thread() { 
       @Override 
       public void run() { 
        Display.getDefault().syncExec(new Runnable() { 
         public void run() { 
          viewer.setInput(ResourcesPlugin.getWorkspace().getRoot()); // this will make the table provider initialize the external source. 
         } 
        }); 
       } 
      }; 

      thread.start(); 

      while(thread.isAlive()) { 
       progress.setWorkRemaining(10000); 
       progress.worked(1); 
      } 

      progress.done(); 
     } 

    }; 

    try { 
     getContainer().run(false, false, runnable); 
    } catch(Exception e) { 
     throw new Exception("Could not access data store", e); 
    } 
} 

這種方法時,嚮導頁的調用setVisible()獲取然後調用 - 方法被調用,並應,幾秒鐘後,設定瀏覽器的輸入。然而,這從來就不會發生,因爲最內層的run()方法永遠不會被執行。

有關Eclipse嚮導中如何處理長時間運行(其中沒有準確估計值)的任何提示將非常感謝!

+0

我沒有看到你的方法的價值。只要你不知道它會持續多久,給用戶的反饋就是錯誤的。爲什麼不測量一段時間內整個操作的長度,然後決定每步應該做多少滴答?當你用'beginTask(String,int)'開始時,int應該是整個跨度。請參閱[IProgressMonitor API](http://help.eclipse.org/helios/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/core/runtime/IProgressMonitor.html)。 – mliebelt

+0

感謝您的評論。我的目標是讓用戶反饋一些事情正在發生,而不僅僅是阻止用戶界面。外部資源(實際上基於文件的三重存儲)的初始化只需要幾秒鐘(5-10),但不能真正被測量/估計。它發生在單個框架方法中,並且取決於已存儲的數據量。 – mwuersch

回答

1

我假設它對你「不起作用」的原因是輸入準備在UI線程中完成,這意味着進度條無法更新。更好的方法是預先準備好輸入,然後在觀看者之後僅將輸入設置給觀看者。

+0

這是一個好點 - 我會檢查準備運行的線程。 – mwuersch

1

我給出了一個簡單的例子,關於如何使用IRunnableWithProgressProgressMonitorDialog來執行未知數量的任務。首先,執行IRunnableWithProgress,執行實際任務。這個實現可能是一個內部類。現在

public class MyRunnableWithProgress implements IRunnableWithProgress { 
    private String _fileName; 

    public MyRunnableWithProgress(String fileName) { 
     _fileName = fileName; 
    } 

    @Override 
    public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { 
     int totalUnitsOfWork = IProgressMonitor.UNKNOWN; 
     monitor.beginTask("Performing read. Please wait...", totalUnitsOfWork); 
     performRead(_fileName, monitor); // This only performs the tasks 
     monitor.done(); 
    } 
} 

,可以創建一個通用的實施ProgressMonitorDialog如下可能被用於在需要進度監視器對話框等地。

public class MyProgressMonitorDialog extends ProgressMonitorDialog { 

    private boolean cancellable; 

    public MyProgressMonitorDialog(Shell parent, boolean cancellable) { 
     super(parent); 
     this.cancellable = cancellable; 
    } 

    @Override 
    public Composite createDialogArea(Composite parent) { 
     Composite container = (Composite) super.createDialogArea(parent); 
     setCancelable(cancellable); 
     return container; 
    } 
} 

在拿到所需執行的任務可以如下得到它與一個進度對話框處理被調用。

boolean cancellable = false; 
IRunnableWithProgress myRunnable = new MyRunnableWithProgress(receivedFileName); 
ProgressMonitorDialog progressMonitorDialog = new MyProgressMonitorDialog(getShell(), cancellable); 

try { 
    progressMonitorDialog.run(true, true, myRunnable); 
} catch (InvocationTargetException e) { 
    // Catch in your best way 
    throw new RuntimeException(e); 
} catch (InterruptedException e) { 
    //Catch in your best way 
    Thread.currentThread().interrupt(); 
} 

希望這有助於!

+0

謝謝,IProgressMonitor.UNKNOWN肯定是一個好主意,但是,我會,但有興趣如何處理案件,其中performRead(.. )將是一個(阻塞)框架方法,不接受我可以調用working()的監視器。 – mwuersch