2013-10-14 1 views
0

Я создаю приложение Java с загрузчиком. Моя проблема заключается в том, что индикатор выполнения не работает. Я хочу, чтобы индикатор выполнения показывал ход загрузки, но не удался. Вот часть моего кода. Прогрессбар просто застрял на 0% ...Java - Как использовать JProgressBar с SwingWorker

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

Прочтите раздел из учебника Swing по How to Use Progress Bars для рабочего примера, в котором используется SwingWorker.

Начните с чего-то, что работает и внесите изменения для вашего конкретного требования. Если у вас все еще есть проблемы, отправьте сообщение SSCCE, которое демонстрирует проблему.

2

Такая вещь менее тривиальная, чем кажется. copyURLToFile() будет заблокирован до завершения копирования, так что вы получите только два события - 0% и 100%.

Если вы хотите показать прогресс во время загрузки, вам необходимо знать файл length перед загрузкой (так что вы можете вычислить проценты). Вы могли бы получить это - возможно, путем запроса HTTP HEAD перед запуском копии - но есть ли в ответе Content-Length поле в ответе, зависит от сервера - для кодирования с чередованием вы не получаете эту информацию (хотя вы, возможно, сможете чтобы заставить некоторые серверы сообщать вам, выдав запрос HTTP 1.0). В противном случае вы можете обмануть и выбрать произвольное количество байтов.

После того, как у вас есть длину или приближение, вы можете либо

  • Запуск таймера и периодически проверять количество байтов, загруженных до сих пор, и сравнить его с размером, ИЛИ
  • Открыть URL как InputStream и сделать свой собственный цикл, чтобы скопировать байты, и на каждой итерации цикла, обновить прогресс бар

в любом случае, убедитесь, что вы используете EventQueue.invokeLater() обновить value Prope прогресс бар в rty или у вас могут быть проблемы с блокировкой - не безопасно изменять компоненты Swing из любого потока, кроме потока событий.

+0

Длина файла = размер файла? Мой загрузчик проанализирует XML-файл и получит содержимое «URL» в файле XML и загрузит его с помощью Common-IO. – Jeremy

+0

Да, длина файла = размер файла.Протокол HTTP позволяет два способа отправить файл - старомодный HTTP 1.0 download, где заголовок '' Content-Length' сообщает вам, сколько байтов вы загрузите, прежде чем загружать их. HTTP 1.1 предлагает «chunked» кодировку, где сервер продолжает передавать небольшие куски байтов, каждому из которых предшествует количество байтов в этом фрагменте. В этом случае вы не знаете, сколько времени вы загружаете. Итак, для кодирования с кодировкой, вы не знаете, сколько байтов вы получите. Если вы знаете средний размер, вы можете догадаться об этом ... –

+0

Но неважно, если вы хотите показать фактический прогресс - какой процент вы сделали - вам нужно каким-то образом прослушать скачивание, пока он находится в прогресса и обновления. Вы всегда можете делать «неопределенный» режим на панели выполнения, и в этом случае точное знание того, сколько байтов осталось загрузить, не требуется. –

0

Похоже, что ваш индикатор выполнения не обновляется, потому что вы его не обновляете. Во-первых, вам нужно на самом деле вызвать setProgress() внутри doInBackground() для события изменения свойства для запуска. Кроме того, поскольку я не знаю, где ваша переменная прогресса изнутри propertyChange, вам нужно вызвать evt.getNewValue(), чтобы получить прогресс от setProgress(). В-третьих, вы вызываете addPropertyChangeListener() после вызова execute(), и вы должны делать это наоборот.

Кроме того, что сказал Тим, потому что вы не сможете легко обновлять свой прогресс периодически задачей, состоящей в основном из одного вызова метода. Вы ничего не можете сделать, пока метод не вернется, и все будет сделано, когда это произойдет.

 Смежные вопросы

  • Нет связанных вопросов^_^