user2154283
user2154283

Reputation: 291

Java JFrame update in loop

Before coming here, I have searched all over the web and read dozens of topic talking about this but I can't fix my problem.

I want to show the progress of an upload. In the following code, everything works, except that my JFrame does not update. I am using a technique I found on another topic, but it doesn't seem to work. I think it will be more simple if you take a look at my code (I erased the instructions that aren't related to the problem).

/*
 * Correct imports have been done
 */

class GUI extends JFrame {
    public JPanel pan;

    public GUI(JPanel panel) {
        super("Uploading...");
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        setPreferredSize(new Dimension(600, 500));
        setMinimumSize(new Dimension(600, 500));
        setMaximumSize(new Dimension(600, 500));
        setDefaultCloseOperation(this.DO_NOTHING_ON_CLOSE);
        setLocationRelativeTo(null);

        pan = panel;
        pan.setLayout(new BoxLayout(pan, BoxLayout.Y_AXIS));

        setContentPane(pan);
        setVisible(true);   
    }
}

public class GUIUpload {
    private static GUI ui;

    public static void main(String args[]) {
        JPanel main = new JPanel();
        ui = new GUI(main); // create and display GUI        
        uploadLoop(args, main); // start the upload loop

        /*
         * After upload is finished
         */
            JButton jb = new JButton("Ok");
        jb.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                ui.setVisible(false);               
            }
        });

        ui.getContentPane().add(jb);
        ui.getContentPane().repaint();
    }

    private static void uploadLoop(String[] paths, JPanel monitor) {
        /*
         * Upload starts here
         */
        long transfered;
        long size;
        InputStream inputStream;        

        FTPClient ftpClient = new FTPClient();
        try {
        ftpClient.connect("xxxxxx", 21);
            boolean success = ftpClient.login("xxxxxx", "xxxxxx");
            /*
             * Sending
             */
            for (int i = 0; i < 4; i++){
                if (paths[i] != null){
                    File localFile = new File(paths[i]);
                    String remoteFile = "/public_html/papers/" + i + ".pdf";
                    JLabel label = new JLabel("Uploading...");
                    ui.getContentPane().add(label);
                    ui.repaint();

                    inputStream = new FileInputStream(localFile);   
                    // Monitoring misc
                    size = localFile.length();
                    transfered = 0;
                    int percentage = 0;
                                    // Progress bar
                    JProgressBar pgb = new JProgressBar();
                    pgb.setValue(0);
                    ui.getContentPane().add(pgb);
                    ui.repaint();
                    // Upload routine
                    OutputStream outputStream = ftpClient.storeFileStream(remoteFile);;
                    byte[] bytesIn = new byte[4096];
                    int read = 0;
                    while ((read = inputStream.read(bytesIn)) != -1) {
                        outputStream.write(bytesIn, 0, read);
                        transfered += read;
                        percentage = (int)(transfered * 100.0 / size + 0.5);
                        System.out.println(percentage);
                        pgb.setValue(percentage);
                        ui.repaint();
                    }
                    inputStream.close();
                    outputStream.close();
                    boolean completed = ftpClient.completePendingCommand();
                    /*
                     * End of upload
                     */ 
                }   
            }
        } // end try
        catch (Exception e){
            // Do nothing}
        } // end catch
    } // end upload method
}

The percentage works fine. The file transfer works fine. The GUI frame only updates after when I repaint it in the main method of the GUIUpload class. When it repaints, I can see that all the labels and progressbars have been correctly added and updated (the progress bars are showing the maximum value.

So.. it's been quite a while that I'm searching how to do this, and I've tried using threads, I've tried a lot of things, but none worked (or I did something wrong when trying them).

Thanks a lot to anyone who will be able to help me out.

Best regards.

Upvotes: 0

Views: 955

Answers (1)

Reimeus
Reimeus

Reputation: 159854

  • Swing is single-threaded. When you perform resource heavy tasks such as file download, you prevent Swing from repainting.
  • It's unsurprising that raw Threads didn't work as Swing has it's own concurrency features that provide a means of dealing with time-consuming background tasks. Threads were not designed to interact with swing components.
  • Use a SwingWorker.

Upvotes: 1

Related Questions