2012-10-26 36 views
2

我想我从这个问题的答案投票找到的代码:Download file using java apache commons?的JProgressBar不会更新

这是一个下载的应用程序,需要一点看,(我没有太多熟悉JFrames和是ActionEvent )

Download.java

package main; 

public class Download extends JFrame implements Runnable{ 

    public static int total; 
    public static int done; 

    private static class ProgressListener implements ActionListener{ 

     @Override 
     public void actionPerformed(ActionEvent e) { 

      done = (int)((DownloadCountingOutputStream) e.getSource()).getByteCount(); 
      jbar.repaint(); 
      DownloadCountingOutputStream.parent.draw((int)((DownloadCountingOutputStream) e.getSource()).getByteCount());//redraw 
      DownloadCountingOutputStream.parent.repaint(); 
     } 
    } 

    public static JProgressBar jbar = new JProgressBar(); 



    public void draw(int downloaded){System.out.println("downloaded: "+downloaded+ " Total: "+total); 

     if (downloaded== 0){ 

     Container cont = new Container();  
     setDefaultCloseOperation(3); 
     setSize(600, 450); 
     setResizable(false); 
     setVisible(true); 

     cont.add(jbar);  
     jbar.setBounds(40, 50, 500, 50);     
     jbar.setMaximum(total);//The total value of bytes to download 
     //jbar.setValue(50); 
     add(cont); 

     jbar.setVisible(true); 
     } 

     jbar.setValue(downloaded);  
      //This should update the value of the progress Bar 
    } 

    public void run() { 


     URL dl = null; 
     File fl = null; 
     OutputStream os = null; 
     InputStream is = null; 
     ProgressListener progressListener = new ProgressListener(); 

     draw(done); 

     try { 
      fl = new File(System.getProperty("user.home").replace("\\", "/") + "/Desktop/afile.rar"); 
      dl = new URL("https://dl.dropbox.com/u/48076798/afile.rar"); 
      os = new FileOutputStream(fl); 
      is = dl.openStream(); 

      total = Integer.parseInt(dl.openConnection().getHeaderField("Content-Length")); 

      String total = dl.openConnection().getHeaderField("Content-Length"); 

      DownloadCountingOutputStream dcount = new DownloadCountingOutputStream(os); 
      dcount.setListener(progressListener); 
      dcount.setParent(this); 

      IOUtils.copy(is, dcount); 

     } catch (Exception e) { 
      System.out.println(e); 
     } finally { 
      if (os != null) { 
       try { 
        os.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
      if (is != null) { 
       try { 
        is.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 

} 

DownloadCountingOutputStream.java

package main; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.io.IOException; 
import java.io.OutputStream; 

import org.apache.commons.io.output.CountingOutputStream; 

public class DownloadCountingOutputStream extends CountingOutputStream { 

    private ActionListener listener = null; 
    public static Download parent; 

    public DownloadCountingOutputStream(OutputStream out) { 
     super(out); 
    } 

    public void setListener(ActionListener listener) { 
     this.listener = listener; 
    } 

    public void setParent(Download o){ 

     parent = o; 
    } 

    @Override 
    protected void afterWrite(int n) throws IOException { 
     super.afterWrite(n); 
     if (listener != null) { 
      listener.actionPerformed(new ActionEvent(this, 0, null)); 
     } 
    } 

} 
+3

你正在做的Swing调用关闭进度更新的Swing事件线程,并且看起来并不尊重Swing的线程规则。考虑使用SwingWorker进行后台工作,并根据Swing进度和SwingWorker教程显示的内容更新worker的进度属性。 –

回答

3

从您提供的代码示例中很难看出...

此问题的主要原因是尝试在阻塞事件分派线程(EDT)时更新UI。

重要的是永远不要在EDT内进行长时间运行或阻塞操作,因为这样可以防止重新绘制请求被执行。

欲了解更多信息,有一个通过Concurrency in Swing

阅读下面的例子演示了如何使用SwingWorker提供该重新同步与UI

public class TestProgress { 

    public static void main(String[] args) { 
     new TestProgress(); 
    } 

    public TestProgress() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException ex) { 
       } catch (InstantiationException ex) { 
       } catch (IllegalAccessException ex) { 
       } catch (UnsupportedLookAndFeelException ex) { 
       } 

       ProgressPane progressPane = new ProgressPane(); 
       JFrame frame = new JFrame("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(progressPane); 
       frame.setSize(200, 200); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 

       progressPane.doWork(); 
      } 
     }); 
    } 

    public class ProgressPane extends JPanel { 

     private JProgressBar progressBar; 

     public ProgressPane() { 

      setLayout(new GridBagLayout()); 
      progressBar = new JProgressBar(); 

      add(progressBar); 

     } 

     public void doWork() { 

      Worker worker = new Worker(); 
      worker.addPropertyChangeListener(new PropertyChangeListener() { 
       @Override 
       public void propertyChange(PropertyChangeEvent evt) { 
        if ("progress".equals(evt.getPropertyName())) { 
         progressBar.setValue((Integer) evt.getNewValue()); 
        } 
       } 
      }); 

      worker.execute(); 

     } 
    } 

    public class Worker extends SwingWorker<Object, Object> { 

     @Override 
     protected Object doInBackground() throws Exception { 

      for (int index = 0; index < 1000; index++) { 
       int progress = Math.round(((float) index/1000f) * 100f); 
       setProgress(progress); 

       Thread.sleep(10); 
      } 

      return null; 
     } 
    } 
}