1

bufferedInputStreamを使用して大きなファイルを保存するJavaアプリケーションを開発しています。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を使用してプログレスバーを更新し、PropertyChangeListenerのダイアログを閉じdoneます。どちらもイベント処理スレッドで実行されることが保証されています。

上記でリンクしたjavadocに必要なものに非常に近い例があります。

于 2013-03-05T09:53:10.113 に答える
0

それをすべて捨てて、javax.swing.ProgressMonitorInputStream.

于 2013-03-05T21:44:13.323 に答える