1

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

这是主要的应用程序片段:

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

3 回答 3

3

您必须在另一个线程(即非 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();
于 2013-03-05T09:06:27.220 回答
3

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

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

于 2013-03-05T09:53:10.113 回答
0

把它全部扔掉并使用javax.swing.ProgressMonitorInputStream.

于 2013-03-05T21:44:13.323 回答