【问题标题】:Using swing GUI to make a progress bar show up while downloading a file [duplicate]下载文件时使用swing GUI显示进度条[重复]
【发布时间】:2014-02-22 12:51:06
【问题描述】:

我目前有一门课,它应该在下载文件时向我展示一个简单的表单。它正在工作,但进度条没有更新,我只能在下载完成后才能看到它。有人可以帮我吗?

import java.awt.FlowLayout;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JProgressBar;

public class Downloader {

    public Downloader(String site, File file) {
        JFrame frm = new JFrame();
        JProgressBar current = new JProgressBar(0, 100);
        current.setSize(50, 100);
        current.setValue(0);
        current.setStringPainted(true);
        frm.add(current);
        frm.setVisible(true);
        frm.setLayout(new FlowLayout());
        frm.setSize(50, 100);
        frm.setDefaultCloseOperation(EXIT_ON_CLOSE);
        try {
            URL url = new URL(site);
            HttpURLConnection connection
                    = (HttpURLConnection) url.openConnection();
            int filesize = connection.getContentLength();
            float totalDataRead = 0;
            try (java.io.BufferedInputStream in = new java.io.BufferedInputStream(connection.getInputStream())) {
                java.io.FileOutputStream fos = new java.io.FileOutputStream(file);
                try (java.io.BufferedOutputStream bout = new BufferedOutputStream(fos, 1024)) {
                    byte[] data = new byte[1024];
                    int i;
                    while ((i = in.read(data, 0, 1024)) >= 0) {
                        totalDataRead = totalDataRead + i;
                        bout.write(data, 0, i);
                        float Percent = (totalDataRead * 100) / filesize;
                        current.setValue((int) Percent);
                    }
                }
            }
        } catch (IOException e) {
            javax.swing.JOptionPane.showConfirmDialog((java.awt.Component) null, e.getMessage(), "Error",
                    javax.swing.JOptionPane.DEFAULT_OPTION);
        }
    }
}

【问题讨论】:

标签: java swing download progress-bar progress


【解决方案1】:

你的问题是一个经典的 Swing 并发问题。解决方案一如既往 - 在后台线程中执行长时间运行的代码,例如可以使用 SwingWorker 找到。

例如,

import java.awt.FlowLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutionException;

import javax.swing.JFrame;
import javax.swing.SwingWorker;

import static javax.swing.JFrame.EXIT_ON_CLOSE;

import javax.swing.JProgressBar;

public class Downloader {

   public Downloader(String site, File file) {
      JFrame frm = new JFrame();
      final JProgressBar current = new JProgressBar(0, 100);
      current.setSize(50, 100);
      current.setValue(0);
      current.setStringPainted(true);
      frm.add(current);
      frm.setVisible(true);
      frm.setLayout(new FlowLayout());
      frm.setSize(50, 100);
      frm.setDefaultCloseOperation(EXIT_ON_CLOSE);
      final Worker worker = new Worker(site, file);
      worker.addPropertyChangeListener(new PropertyChangeListener() {

         @Override
         public void propertyChange(PropertyChangeEvent pcEvt) {
            if ("progress".equals(pcEvt.getPropertyName())) {
               current.setValue((Integer) pcEvt.getNewValue());
            } else if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) {
               try {
                  worker.get();
               } catch (InterruptedException | ExecutionException e) {
                  // handle any errors here
                  e.printStackTrace(); 
               }
            }

         }
      });
      worker.execute();
   }
}

class Worker extends SwingWorker<Void, Void> {
   private String site;
   private File file;

   public Worker(String site, File file) {
      this.site = site;
      this.file = file;
   }

   @Override
   protected Void doInBackground() throws Exception {
      URL url = new URL(site);
      HttpURLConnection connection = (HttpURLConnection) url
            .openConnection();
      int filesize = connection.getContentLength();
      int totalDataRead = 0;
      try (java.io.BufferedInputStream in = new java.io.BufferedInputStream(
            connection.getInputStream())) {
         java.io.FileOutputStream fos = new java.io.FileOutputStream(file);
         try (java.io.BufferedOutputStream bout = new BufferedOutputStream(
               fos, 1024)) {
            byte[] data = new byte[1024];
            int i;
            while ((i = in.read(data, 0, 1024)) >= 0) {
               totalDataRead = totalDataRead + i;
               bout.write(data, 0, i);
               int percent = (totalDataRead * 100) / filesize;
               setProgress(percent);
            }
         }
      }
      return null;
   }
}

【讨论】:

  • 感谢您,它可以工作,但是,它会在 20% java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: the value should be from 0 to 100 at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:188) at javax.swing.SwingWorker.get(SwingWorker.java:602) at Downloader$1.propertyChange(Downloader.java:49) 处停止
  • @woutwoot:发生错误时百分比的值是多少?调用 setProgress(int progress) 时,您只能传入 0 到 100 之间的值。如果百分比太大,比如 101,请考虑使用 if 块 -- if (percent &gt; 100) {percent = 100) 或类似的。
  • 我刚刚在测试,由于某种原因,它只适用于大于 20MB 的文件。错误发生@worker.get();
  • @woutwoot:worker.get() 方法将捕获doInBackground() 运行期间抛出的异常。尝试隔离错误,如果仍然卡住,请使用您的 minimal runnable example program 和您的数据发布一个新问题。
  • 错误原因是int溢出。要解决此问题,您必须将 totalDataReadfilesize 更改为 long,然后为 percent 的结果添加强制转换。进行此更改后,您应该能够下载最大 2GB 的文件。
猜你喜欢
  • 2016-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多