2013-10-14 32 views
0

我正在使用下载程序创建Java应用程序。我的问题是,进度条不起作用。我想要我的进度条显示下载进度但失败。这是我的代码的一部分。只是停留在0%的进度...Java - 如何在SwingWorker中使用JProgressBar

Download.class

public void startDownload() 
{ 
    ExecutorService executor = Executors.newSingleThreadExecutor(); 
    FutureTask<Void> verDownloader = new FutureTask<Void>(vd); 
    FutureTask<Void> launcher = new FutureTask<Void>(dd); 
    executor.execute(verDownloader); 
    executor.execute(launcher); 
    executor.shutdown(); 
} 

VersionDownloader.class

public class VersionDownloader implements Callable<Void>, PropertyChangeListener 
{ 
    @Override 
    public Void call() throws Exception 
    { 
        done = false; 
        final SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() 
        { 
         @Override 
         protected Void doInBackground() throws Exception 
         { 
          try 
          { 
           URL fileURL = new URL(url); 
           org.apache.commons.io.FileUtils.copyURLToFile(fileURL, path); 
          } 
          catch(Exception e) 
          { 

          } 
          return null; 
         } 

         @Override 
         public void done() 
         { 
          done = true; 

          try 
          { 
           Thread.sleep(1000); 
          } 
          catch (InterruptedException e) 
          { 
           e.printStackTrace(); 
          } 
         } 

        }; 
        worker.execute(); 
        worker.addPropertyChangeListener(this); 
        worker.get(); 
       } 
      } 
     } 
     catch(Exception e) 
     { 

     } 
     return null; 
    } 

    @Override 
    public void propertyChange(PropertyChangeEvent evt) 
    { 
     if(!done) 
     { 
      int progress_a = progress; 
      //launcher.frame.progress is a JProgressBar 
      launcher.frame.progress.setValue(progress_a); 
     } 
    } 


} 

是,任何代码错了吗?

回答

1

阅读关于How to Use Progress Bars的Swing教程中有关使用SwingWorker的示例的一节。

从某些工作开始,并根据您的特定要求进行更改。如果你仍然有问题,然后张贴SSCCE,说明问题。

2

这种事情不像听起来那么微不足道。 copyURLToFile()将会阻止,直到复制完成,这样只会给你两个事件 - 0%和100%。

如果要在下载过程中显示进度,则有一个先决条件:在下载开始之前必须知道文件长度(因此您可以计算百分比)。你可以通过在开始复制之前发出一个HTTP HEAD请求来获得这个信息 - 但是在响应中是否有Content-Length字段取决于服务器 - 对于分块编码,你不会得到这些信息(尽管你可能能够强制一些服务器通过发出HTTP 1.0请求来告诉你)。否则,你可以作弊并选择任意数量的字节。

一旦你的长度或近似,您可以

  • 运行一个计时器,并定期检查,到目前为止下载的字节数,并比较,与大小,或者
  • 打开网址作为InputStream,做你自己的循环复制的字节数,并在每个循环迭代,更新进度条

无论哪种方式,请确保您使用EventQueue.invokeLater()更新进度条的value prope或者你可能会遇到死锁问题 - 从任何线程修改Swing组件是不安全的,除了事件线程。

+0

文件长度=文件大小?我的下载程序将解析XML文件,并在XML文件中获取“URL”的内容并使用Common-IO进行下载。 – Jeremy

+0

是的,文件长度=文件大小。HTTP协议允许两种方式发送文件 - 老式的HTTP 1.0下载,其中“Content-Length”标题告诉你在下载之前将下载多少字节。 HTTP 1.1提供了“分块”编码,即服务器不断传递小块字节,每个字节前面都有该块中的字节数。在这种情况下,你不知道你正在下载的文件有多长。所以对于分块编码,你不知道你会得到多少字节。 如果你知道平均大小,你可以猜测它... –

+0

但是,无论如何,如果你想显示实际的进展 - 你做了多少百分比 - 你需要一些方法来听下载时,它是在进度并更新它。您始终可以在进度条上执行“不确定”模式,在这种情况下,无需准确了解需要下载多少字节。 –

0

看起来您的进度条并未更新,因为您没有更新它。首先,您需要实际调用doInBackground()内的setProgress()以激发属性更改事件。另外,因为我不确定您的进度变量来自propertyChange内部的哪个位置,您需要调用evt.getNewValue()以从setProgress()获取进度。第三,你在调用execute()之后调用addPropertyChangeListener(),你应该反过来做。

此外,蒂姆说,因为你将无法使用基本上由单一方法调用组成的任务定期轻松更新进度。在方法返回之前,你什么也做不了,它在所有的时候都完成了。