2013-11-26 41 views
0

我在這個類中執行任務,對話框彈出爲白色框。打印語句IS打印出我期待的進度值,但直到操作完成後纔在對話框中顯示出來。在對話框結束之前,我可以看到進度條閃爍一毫秒。絕對不知道怎麼回事:\JProgressBar是不可見的,但進度正在更新

public class ProgressDialog extends JDialog { 

    private JProgressBar pb; 
    private SwingWorker<Boolean, Void> task; 

    public SwingWorker<Boolean, Void> getTask(){ 
     return task; 
    } 

    public ProgressDialog(final String call){ 
     setTitle("Working..."); 
     setLayout(new BorderLayout()); 
     setBounds(300,300,300,100); 
     pb = new JProgressBar(0, 100); 
     pb.setValue(0); 
     pb.setVisible(true); 
     pb.setStringPainted(true); 
     add(pb, BorderLayout.CENTER); 
     setVisible(true); 

     task = new SwingWorker<Boolean, Void>(){ 
      public Boolean doInBackground(){   
       switch(call){ 
       case "Category": pb.setValue(Category.getProgress()); 
       while(pb.getValue()<99){ 
        try{ 
         Thread.sleep(500); 
        } catch (InterruptedException e){ 
         Thread.currentThread().interrupt(); 
        } 
        pb.setValue(Category.getProgress()); 
        System.out.println(pb.getValue()); 
        repaint(); 
        revalidate(); 
       } 
       break; 
       } 
       return true; 
      } 
      public void done(){ 
       dispose(); 
      } 
     }; 
    } 
} 

編輯:試過這個改變。沒有骰子。爲什麼我甚至沒有獲得0%的進度條?這是沒有意義的 - 它只有一次是在100%

public class ProgressDialog extends JDialog { 

private JProgressBar pb; 
private SwingWorker<Boolean, Integer> task; 

public SwingWorker<Boolean, Integer> getTask(){ 
    return task; 
} 

public ProgressDialog(final String call){ 
    setTitle("Working..."); 
    setLayout(new BorderLayout()); 
    setBounds(300,300,300,100); 
    pb = new JProgressBar(0, 100); 
    pb.setValue(0); 
    pb.setStringPainted(true); 
    add(pb, BorderLayout.CENTER); 
    setVisible(true); 

    task = new SwingWorker<Boolean, Integer>(){ 
     public Boolean doInBackground(){   
      switch(call){ 
      case "Category": setProgress(Category.getProgress()); 
      while(pb.getValue()<99){ 
       try{ 
        Thread.sleep(500); 
       } catch (InterruptedException e){ 
        Thread.currentThread().interrupt(); 
       } 
       setProgress(Category.getProgress()); 
      } 
      break; 
      } 
      return true; 
     } 

     public void done(){ 
      //dispose(); 
     } 
    }; 

    task.addPropertyChangeListener(new PropertyChangeListener() { 
       public void propertyChange(PropertyChangeEvent evt) { 
        if ("progress".equals(evt.getPropertyName())) { 
         System.out.println((Integer)evt.getNewValue()); 
         pb.setValue((Integer)evt.getNewValue()); 
         pb.revalidate(); 
         pb.repaint(); 
        } 
       } 
      }); 
} 

}

+0

請在更新看答案,特別是ryvantage的答案和代碼,你應該接受。 –

回答

3

你試圖從SwingWorker類的doInBackground方法中設置進度條的狀態,從後臺線程出現。使用SwingWorker的全部原因是允許您在Swing GUI中執行後臺進程,因此您不會從後臺線程進行Swing調用,因此您不會將Swing線程與長時間的線程綁定在一起,運行一段代碼。

您不應該從此後臺進程進行Swing調用。而是使用發佈/處理方法,因爲教程將向您展示。或者更好的辦法是設置SwingWorker的progress字段,並在SwingWorker上使用PropertyChangeListener來允許進度條對它作出反應。

無論如何,底線:

  • 使用的SwingWorker做後臺工作。
  • 不要在SwingWorker的doInBackground方法中進行Swing調用。
  • 使用發佈將數據從背景方法推送到Swing線程領域。
  • 使用處理方法來處理推送的這些數據。
  • SwingWorker具有progress屬性,該屬性在允許Swing代碼響應背景狀態變化時也很方便。
  • 如果你走這條路線,使用PropertyChangeListener。
  • 你差不多從不想使用setBounds(...)或null佈局。相信我是一個寫過數百個Swing程序的人,最後這個人會咬你的。
  • 它看起來好像您的類別正在使用靜態方法獲取其進展。再一次,這是你幾乎從不想做的事情。進度字段建議狀態,並且這應該是對象的實例字段的一部分,從不靜態。
+0

我嘗試了兩個建議,他們都導致進度條只有在達到100時纔會收到一個更新。我比我開始更困惑 –

+0

@MichaelGroleau:如果您已經做出更改,請將代碼作爲編輯發佈到您的原來的問題。不要更改原始問題的代碼和文本,但將新信息添加到底部。 –

+0

完成後,評論 –

2

這是一個SSCCE來演示如何更新您的JProgressBar。複製/粘貼並運行它。

請注意我們如何通過調用publish(i)來更新進度條,它將整數發送到process()方法。 SwingWorker以塊結果的方式將結果發送給process()方法,但我們僅使用Integer來更新JProgressBar,因此我們只關心它的最後一個塊。在這個SSCCE,我們從1-1000。如果您檢查控制檯,您會看到1-1000之間的很多數字會被忽略,因爲我們正在更新太快而無法跟上(但沒關係,這就是爲什麼它會以塊形式提供結果)。

注意:process()方法最初是爲程序員設計的,用於從其長時間運行的進程返回實時結果並更新GUI。因此,如果您正在執行數據庫提取,則可以使用返回的結果更新JTable。雖然我討厭這樣做。所以99%的時間我只是使用「不確定的」JProgressBar,並等到done()方法發佈我的結果。但是,有時我會使用「確定性」JProgressBar並像我們在此SSCCE中那樣更新。我從來沒有使用過process()來返回併發布實際數據。 :)但是,這是它最初設計的目的。

import java.util.List; 
import java.util.concurrent.ExecutionException; 
import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JProgressBar; 
import javax.swing.SwingUtilities; 
import javax.swing.SwingWorker; 

/** 
* 
* @author Ryan 
*/ 
public class Test { 

    public static void main(String args[]) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       go(); 
      } 
     }); 
    } 

    public static void go() { 
     JFrame frame = new JFrame(); 
     JProgressBar jpb = new JProgressBar(); 
     jpb.setIndeterminate(false); 
     int max = 1000; 
     jpb.setMaximum(max); 
     frame.add(jpb); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     new Task(jpb, max).execute(); 
    } 

    static class Task extends SwingWorker<Void, Integer> { 

     JProgressBar jpb; 
     int max; 
     public Task(JProgressBar jpb, int max) { 
      this.jpb = jpb; 
      this.max = max; 
     } 

     @Override 
     protected void process(List<Integer> chunks) { 
      jpb.setValue(chunks.get(chunks.size()-1)); // The last value in this array is all we care about. 
      System.out.println(chunks.get(chunks.size()-1)); 
     } 

     @Override 
     protected Void doInBackground() throws Exception { 
      for(int i = 0; i < max; i++) { 
       Thread.sleep(10); // Sleep for 1/10th of a second 
       publish(i); 
      } 
      return null; 
     } 

     @Override 
     protected void done() { 
      try { 
       get(); 
       JOptionPane.showMessageDialog(jpb.getParent(), "Success", "Success", JOptionPane.INFORMATION_MESSAGE); 
      } catch (ExecutionException | InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

編輯:我創建了一個圖處理SwingWorker時,這應該是一個有益的參考,讓你知道在哪裏放置你的代碼。

enter image description here

+0

尼斯SSCCE,謝謝,1+ –

+0

@HovercraftFullOfEels,你怎麼看圖?有用? – ryvantage

+0

它看起來非常好! –