1

My swingworker won't repaint my progress bar(I have 2 classes).

This is my file downloader code. It puts percent of download in progress bar.

public class Downloader extends SwingWorker<String, Integer> {

 private String fileURL, destinationDirectory;
 private int fileTotalSize;

 public void DownloaderF(String file, String dir) {
    this.fileURL = file;
    this.destinationDirectory = dir;
 }

 @Override
 protected String doInBackground() throws Exception {
    try {
        URL url = new URL(fileURL);
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        String downloadedFileName = fileURL.substring(fileURL.lastIndexOf("/")+1);
        int filesize = httpConn.getContentLength();
        int responseCode = httpConn.getResponseCode();
        byte[] buffer = new byte[4096];
        int bytesRead = 0;
        int i = 0;
        int total = 0;
        BufferedInputStream in = new BufferedInputStream(httpConn.getInputStream());
        FileOutputStream fos = new FileOutputStream(destinationDirectory + File.separator + downloadedFileName);
        BufferedOutputStream bout = new BufferedOutputStream(fos,4096);
        while ((i=in.read(buffer,0,4096))>=0) {
            total = total + i;
            bout.write(buffer,0,i);
            fileTotalSize = (total * 100) / filesize;
            publish(fileTotalSize);
        }
        bout.close();
        in.close();
    } catch(FileNotFoundException FNFE) {
        System.out.print("HTTP: 404!");
    } catch (IOException ex) {
        Logger.getLogger(Downloader.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
}

 @Override
 protected void process(List<Integer> chunks) {
    try {
        Skin barValue = new Skin(); 
        barValue.setBar(fileTotalSize);
        //System.out.print("PROCESS:" + fileTotalSize + "\n");
    } catch (Exception ex) {
        ex.printStackTrace();
    }
 }
}

This is my button code and progress bar value change method:

private void LoginButtonActionPerformed(java.awt.event.ActionEvent evt) {                                            
    // TODO add your handling code here:
    // Дебаг
    Downloader downloadFile = new Downloader();
    downloadFile.DownloaderF("http://ipv4.download.thinkbroadband.com/100MB.zip", ".");
    downloadFile.execute();
}                                           

public void setBar(int Value) {
    DownloadBar.setValue(Value);
    DownloadBar.repaint();

    System.out.print("1\n");
}

"1\n" will be printed, but progress bar won't move.

Sorry for my bad english.

  • what is your minValue and maxValue of progress bar – Shahrzad Apr 30 '14 at 18:00
  • your `fileTotalSize` is int but u r pushing into a float, check this and print on console weather it is correct (instead of printing 1\n print value+"\n" for test). – Shahrzad Apr 30 '14 at 18:33
  • I m running same code just fine instead of publish i directly set value of jprogress bar(I do not have your full code), but the difference is as min max is 0-100 so if total file size is much more then percentage will be in fraction, but setValue requires int, so casted to 0 (removed fration) so after long time u will see the progress; solution increase the max range – Shahrzad Apr 30 '14 at 19:00

2 Answers2

2

Most likely, your problem comes from this line:

Skin barValue = new Skin();

You are recreating a new instance of you Skin class instead of referencing one that already exists. Therefore, you most likely point to something that is probably not even displayed and hence you don't see anything happening.

The proper way to go is to provide to your class Downloader a reference to the original Skin containing your displayed "progress bar".

FYI:

  • No need to call repaint() on a JProgressBar when you change its value (the progress bar will do it for you)
  • Please follow Java naming conventions (ie, method names and variables must start with a lower case letter): your code is a lot harder to read for experienced users.

Here is a sample code derived from yours (although I made a few shortcuts) that actually works correctly as expected:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Skin {

    private JProgressBar DownloadBar;

    public static class Downloader extends SwingWorker<String, Integer> {

        private final String fileURL, destinationDirectory;
        private int fileTotalSize;
        private final Skin barValue;

        public Downloader(Skin skin, String file, String dir) {
            this.barValue = skin;
            this.fileURL = file;
            this.destinationDirectory = dir;
        }

        @Override
        protected String doInBackground() throws Exception {
            try {
                URL url = new URL(fileURL);
                HttpURLConnection httpConn = (HttpURLConnection) url
                        .openConnection();
                String downloadedFileName = fileURL.substring(fileURL
                        .lastIndexOf("/") + 1);
                int filesize = httpConn.getContentLength();
                int responseCode = httpConn.getResponseCode();
                byte[] buffer = new byte[4096];
                int bytesRead = 0;
                int i = 0;
                int total = 0;
                BufferedInputStream in = new BufferedInputStream(
                        httpConn.getInputStream());
                FileOutputStream fos = new FileOutputStream(
                        destinationDirectory + File.separator
                                + downloadedFileName);
                BufferedOutputStream bout = new BufferedOutputStream(fos, 4096);
                while ((i = in.read(buffer, 0, 4096)) >= 0) {
                    total = total + i;
                    bout.write(buffer, 0, i);
                    fileTotalSize = total * 100 / filesize;
                    publish(fileTotalSize);
                }
                bout.close();
                in.close();
            } catch (FileNotFoundException FNFE) {
                System.out.print("HTTP: 404!");
            } catch (IOException ex) {
                Logger.getLogger(Downloader.class.getName()).log(Level.SEVERE,
                        null, ex);
            }
            return null;
        }

        @Override
        protected void process(List<Integer> chunks) {
            barValue.setBar(fileTotalSize);
        }
    }

    private void loginButtonActionPerformed(java.awt.event.ActionEvent evt) {
        Downloader downloadFile = new Downloader(this,
                "http://ipv4.download.thinkbroadband.com/100MB.zip", ".");
        downloadFile.execute();
    }

    protected void initUI() throws MalformedURLException {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton login = new JButton("Login");
        login.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                loginButtonActionPerformed(e);
            }
        });
        DownloadBar = new JProgressBar();
        frame.add(login, BorderLayout.NORTH);
        frame.add(new JLabel(new ImageIcon(new URL(
                "http://home.scarlet.be/belperret/images/image1.jpg"))));
        frame.add(DownloadBar, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
    }

    public void setBar(int Value) {
        DownloadBar.setValue(Value);
        DownloadBar.repaint();

        System.out.println("1");
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    new Skin().initUI();
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}
Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117
  • Thanks for answer, but i have 2 classes and i need to create instance. – user3590378 May 01 '14 at 05:45
  • @user3590378: post an [SSCCE](http://sscce.org) if you want better help. All I can tell you is that creating a new instance is the problem and passing a reference is the solution. This is just a problem that you don't understand what instances mean. Btw, my explanation also contains two classes. – Guillaume Polet May 01 '14 at 18:55
0

You are doing the publish(fileTotalSize) correctly, so I think it might be your process code. Try this change:

protected void process(List<Integer> chunks) {
   try {
       Skin barValue = new Skin(); 
       barValue.setBar( chunks.get(0) );
       //System.out.print("PROCESS:" + fileTotalSize + "\n");
   } catch (Exception ex) {
       ex.printStackTrace();
   }
}

I don't have your full code, so I can't test it out.

Alvin Bunk
  • 7,621
  • 3
  • 29
  • 45