2014-02-22 2 views
1

현재 파일을 다운로드하는 동안 간단한 양식을 보여줄 클래스가 있습니다. 작동하지만 진행률 표시 줄이 업데이트되지 않고 다운로드가 완료되면 볼 수 있습니다. 누군가 나를 도울 수 있습니까?스윙 GUI를 사용하여 파일을 다운로드하는 동안 진도 표시 줄을 표시하십시오.

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); 
     } 
    } 
} 
+0

은 EDT (이벤트 발송 쓰레드)를 막지 마십시오. 대신 오랫동안 실행되는 작업을 위해'SwingWorker'를 구현하십시오. 자세한 내용은 [동시성의 동시성] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/)을 참조하십시오. –

+1

그리고 또 다른 dup : [JProgressBar가 다운로드하는 동안 업데이트되지 않습니다.] (http://stackoverflow.com/questions/17400982/jprogressbar-doesnt-update-during-download) –

+2

아직 세 번째 : [내 JProgressBar가 업데이트되지 않습니다. 때까지 100 %] (http://stackoverflow.com/questions/10437590/my-jprogressbar-is-not-updating-until-it-is-100). Google 기술에 대한 작업 시간! ;) –

답변

3

Yours는 고전적인 Swing 동시성 문제입니다. 해결책은 언제나 그렇듯이 SwingWorker에서 찾을 수있는 것과 같이 백그라운드 스레드에서 장기 실행 코드를 수행하는 것입니다. 그렇게 할 때 GUI 것이다 '동결'-

예를 들어,

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; 
    } 
} 
+0

고맙지 만, 작동하지만 20 % java.util.concurrent.ExecutionException 예외로 중지됩니다. java.lang.IllegalArgumentException : java.util.concurrent의 값이 0 - 100 \t이어야합니다. FutureTask.report (FutureTask.java:122) java.util.concurrent.FutureTask.get (FutureTask.java:188)에서 \t javax.swing.SwingWorker.get (SwingWorker.java:602)에서 \t 다운에서 \t $ 1.propertyChange (Downloader.java:49)' – woutwoot

+0

@woutwoot : 오류가 발생했을 때 퍼센트 값은 무엇입니까? 'setProgress (int progress)'를 호출 할 때는 0에서 100 사이의 값만 전달할 수 있습니다. percent가 너무 크면 101이라고 말하면서 if 블록을 사용하는 것을 고려하십시오 - if (percent> 100) {percent = 100} 또는 일부. –

+0

나는 방금 테스트를 해왔으며, 어떤 이유로 든 20MB보다 큰 파일에만 적용됩니다. 이 오류는 @work.get(); – woutwoot

관련 문제