Java uploading percentage progressbar thread

柔情痞子 提交于 2019-12-11 17:58:30

问题


I'm developing a java application where I save big files using bufferedInputStream. I have put a progressbar inside a JDialog which indicates the percentage of uploaded files and which increases every n seconds. The problem is that the application waits indefinitely for the dialog to close and so it never exits. Anyone can help?

here is the main application snippet:

JDialog dialog = new JDialog(Main.getMainFrame(), true);
                    ProgressBarJPanel progressBarJPanel = new ProgressBarJPanel();
                    dialog.setContentPane(progressBarJPanel);
                    dialog.pack();
                    dialog.setVisible(true);
                    while ((val = bufferedInputStream.read()) != -1)
                    {
                        fileOutputStream.write(val);
                    }
                    progressBarJPanel.end();
                    dialog.setVisible(false);

and the incriminated class

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ProgressBarJPanel extends JPanel
        implements ActionListener
{
    private JProgressBar progressBar;
    private Timer timer;
    public Thread updateThread;
    public final static int ONE_SECOND = 1000;
    private JTextArea taskOutput;
    private String newline = "\n";
    int timeNow= 0;
    int progress = 0;

    public ProgressBarJPanel()
    {
        super(new BorderLayout());

        progressBar = new JProgressBar(0, 100);
        progressBar.setValue(0);
        progressBar.setStringPainted(true);
        taskOutput = new JTextArea(5, 20);
        taskOutput.setMargin(new Insets(5,5,5,5));
        taskOutput.setEditable(false);
        taskOutput.setCursor(null);

        JPanel panel = new JPanel();
        panel.add(progressBar);

        add(panel, BorderLayout.PAGE_START);
        add(new JScrollPane(taskOutput), BorderLayout.CENTER);
        setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

        //Create a timer.
        timer = new Timer(ONE_SECOND, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent evt) {
                progressBar.setValue(progress);
                progress+=10;
                String s = "now at "+progress+"%";
                if (s != null) {
                    taskOutput.append(s + newline);
                    taskOutput.setCaretPosition(
                            taskOutput.getDocument().getLength());
                }
            }
        });

    }

    public void end()
    {
        timer.stop();
    }

    public void startProgress()
    {
        timer.start();
    }

    /**
     * Create the GUI and show it. For thread safety, this method should be
     * invoked from the event-dispatching thread.
     */
    private static void createAndShowGUI()
    {
        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);

        //Create and set up the window.
        JFrame frame = new JFrame("ProgressBarDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        JComponent newContentPane = new ProgressBarJPanel();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
                createAndShowGUI();
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

-- EDIT

Here is the solution based on ben75 advice:

JDialog dialog = new JDialog(Main.getMainFrame(), true);
ProgressBarJPanel progressBarJPanel = new ProgressBarJPanel();
dialog.setContentPane(progressBarJPanel);
Runnable r = new Runnable(){
  public void run(){
             SwingUtilities.invokeLater(new Runnable()
             {
                    @Override
                    public void run()
                    {
                       progressBarJPanel.startProgress();
                       dialog.pack();
                       dialog.setVisible(true);
                    }
             });

            //this is the long running job
            while ((val = bufferedInputStream.read()) != -1)
            {
                fileOutputStream.write(val);
            }

            //here is the callback to UI thread
            SwingUtilities.invokeLater(new Runnable(){
                public void run(){
                    progressBarJPanel.end();
                    dialog.setVisible(false);
                }
           }
  };
Thread t = new Thread(r);
t.start();

回答1:


You must do time consumming jobs in another thread (i.e. non UI thread) and at the end of the job callback the UI thread to close the dialog.

More or less how it can be coded:

JDialog dialog = new JDialog(Main.getMainFrame(), true);
ProgressBarJPanel progressBarJPanel = new ProgressBarJPanel();
dialog.setContentPane(progressBarJPanel);
dialog.pack();
dialog.setVisible(true);
Runnable r = new Runnable(){
      public void run(){
                //this is the long running job
                while ((val = bufferedInputStream.read()) != -1)
                {
                    fileOutputStream.write(val);
                }
                //here is the callback to UI thread
                SwingUtilities.invokeLater(new Runnable(){
                    public void run(){
                        progressBarJPanel.end();
                        dialog.setVisible(false);
                    }
               }
      };
Thread t = new Thread(r);
t.start();



回答2:


This would be an ideal job for a SwingWorker - do the upload in doInBackground, and have it call setProgress with an updated progress number every so often. Update the progress bar using a PropertyChangeListener and close the dialog in done, both of which are guaranteed to run on the event handling thread.

There is an example very close to what you need in the javadoc I linked to above.




回答3:


Throw it all away and use a javax.swing.ProgressMonitorInputStream.



来源:https://stackoverflow.com/questions/15219538/java-uploading-percentage-progressbar-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!