2012-03-06 78 views
4

我知道這個問題已經在許多問題上看到,並已得到回答,但仍然無法通過它。更新JProgressBar,同時處理

我只想更新一個progressBar,同時提取一些大的xml文件的東西。 我認爲這足以在不同的線程中耗費時間循環,但是...... 我設法獲得的所有progressBar或者根本沒有顯示,或者在最後關閉之前更新。

實例化附近的某處啓動該應用程序,我有:

public class SomeClass { 
    private SomeClass() { 
     myXMLParser reader = new myXMLParser(); 
     CoolStuff fromXml = reader.readTheXml(); 
    } 
} 

同時顯示和更新一個JDialog用的JProgressBar:

public class LoadingDialog extends JDialog { 
    private JProgressBar progressBar; 
    /* ... */ 
    public void progress() { 
     progressBar.setValue(progressBar.getValue() + 1); 
    } 
} 

所以我有這個myXMLParser

public class myXMLParser { 
    private LoadingDialog loadingDialog = new LoadingDialog(); 

    public CoolStuff readTheXml() { 
     CoolStuff fromXml = new CoolStuff(); 
     while(manyIterations) { 
      loadingDialog.progress(); 
      fromXml.add(some() + xml() + reading()); 
     } 
     return fromXml; 
    } 
} 

我見過很多東西w ith SwingWorker和使用PropertyChange事件更新progressBar,但總是給出示例all-in-one,處理和進度條在同一個類中,並且類中有類,並且自從我開始使用Java之後,能夠將其轉化爲我的情況。

任何幫助?..任何(不太明顯)的建議?

編輯:所以感謝btantlinger它的工作這樣的:

public class SomeClass { 
    private SomeClass() { 
     myXMLParser reader = new myXMLParser(); 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       CoolStuff fromXml = reader.readTheXml(); 
      } 
     }).start(); 
    } 
} 

public class LoadingDialog extends JDialog { 
    private JProgressBar progressBar; 
    /* ... */ 
    public void progress() { 
     progressBar.setValue(progressBar.getValue() + 1); 
    } 
} 

public class myXMLParser { 
    private LoadingDialog loadingDialog = new LoadingDialog(); 

    public CoolStuff readTheXml() { 
     CoolStuff fromXml = new CoolStuff(); 
     while(manyIterations) { 
      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        loadingDialog.progress(); 
       } 
      }); 
      fromXml.add(some() + xml() + reading()); 
     } 
     return fromXml; 
    } 
} 

回答

10

您必須更新在Swing事件分派線程的JProgress吧。您無法修改任何其他線程上的Swing組件。

你唯一的另一種選擇是在開始你的線程之前設置JProgress欄「indeterminate」,在這裏進度條會來回移動。

progBar.setIndeterminate(true); 

見的SwingWorker的javadoc: http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html

如果你不想使用SwingWorker類,另一種選擇是SwingUtilities.invokeLater方法

//inside your long running thread when you want to update a Swing component 
SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 

     //This will be called on the EDT 
     progressBar.setValue(progressBar.getValue() + 1); 


    } 
}); 
0

除由@btantlinger提供的代碼,我在測試後發現它需要額外的一行代碼才能更新e處理時在UI線程上的進度條。見下文。

SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     progressBar.setValue((int)percentage); 
     //below code to update progress bar while running on thread 
     progressBar.update(progressBar.getGraphics());} 
    });