【问题标题】:Java uploading percentage progressbar threadJava上传百分比进度条线程
【发布时间】:2013-03-05 08:57:05
【问题描述】:

我正在开发一个 java 应用程序,我在其中使用 bufferedInputStream 保存大文件。 我在 JDialog 中放置了一个进度条,它指示上传文件的百分比,并且每 n 秒增加一次。 问题是应用程序无限期地等待对话框关闭,因此它永远不会退出。 有人可以帮忙吗?

这里是主要的应用程序sn-p:

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);

和被指控的阶级

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.");
    }
}

-- 编辑

这是基于 ben75 建议的解决方案:

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();

【问题讨论】:

  • 一个建议:使用不同的线程来处理耗时的工作,而不是处理 UI 的工作......
  • 两者如何沟通?同样在上面 Netbeans 警告我 updateThread.start();不应该在构造函数里面,怎么放到外面??
  • 查看this example

标签: java swing concurrency event-dispatch-thread jprogressbar


【解决方案1】:

您必须在另一个线程(即非 UI 线程)中执行耗时的作业,并在作业结束时回调 UI 线程以关闭对话框。

或多或少如何编码:

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();

【讨论】:

  • 进程仍然挂起,因为 progressJBar 是在 Runnable 之外创建的,并且在创建时它会启动自己的线程以每秒更新其进度。
  • 在你的 updateThread 中:而不是直接更新 progressBar :在 UI 线程的回调中进行(使用SwingUtilities.invokeLater(...),如我的帖子所示)。
  • 我根据您的解决方案更新了我的问题,它有效,但我仍然不确定 Thread t 是否真的会一直停止...
【解决方案2】:

这对于SwingWorker 来说是一项理想的工作——在doInBackground 中上传,并让它每隔一段时间调用setProgress 并更新进度号。使用PropertyChangeListener 更新进度条并关闭done 中的对话框,这两者都保证在事件处理线程上运行。

在我上面链接的 javadoc 中有一个非常接近您需要的示例。

【讨论】:

    【解决方案3】:

    扔掉它并使用javax.swing.ProgressMonitorInputStream.

    【讨论】:

    • 怎么样?这更像是一个评论而不是一个答案。
    猜你喜欢
    • 2014-03-05
    • 2017-03-24
    • 1970-01-01
    • 2012-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-03
    相关资源
    最近更新 更多