4

我知道我一定遗漏了一些非常明显的东西,但是每当我在复制文件时尝试使用 ProgressMonitorInputStream 时,我永远不会得到 ProgressDialog 弹出窗口。

我看到的示例除了将它们的输入流包装在 ProgressMonitorInputStream 中之外似乎没有做太多事情。

文档说:

这将创建一个进度监视器来监视读取输入流的进度。如果需要一段时间,会弹出一个 ProgressDialog 来通知用户。如果用户点击 Cancel 按钮,则会在下一次读取时抛出 InterruptedIOException。当流关闭时,所有正确的清理工作都完成了。

setMillisToPopup()这是我放在一起的一个非常简单的示例,即使我的数字非常小,它也不会弹出带有大文件的对话框。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.ProgressMonitorInputStream;
import javax.swing.SwingWorker;

public class ProgressBarDemo extends JFrame {

   private static final long serialVersionUID = 1L;

   private JButton button;

   ProgressBarDemo() 
   {
      button = new JButton("Click me!");
      ButtonActionListener bal = new ButtonActionListener();
      button.addActionListener(bal);

      this.getContentPane().add(button);
   }

   private class ButtonActionListener implements ActionListener 
   {

      @Override
      public void actionPerformed(ActionEvent e) {
         // TODO Auto-generated method stub
         Worker worker = new Worker();
         worker.execute();
         button.setEnabled(false);
      }
   }

   public void go() {

      this.setLocationRelativeTo(null);
      this.setVisible(true);
      this.pack();
      this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }

   private class Worker extends SwingWorker<Void, Void>
   {

      private void copyFile() {

         File file = new File("/Users/mypath/Desktop/WirelessDiagnostics.tar.gz");

         BufferedInputStream bis;
         BufferedOutputStream baos;
         try {
            bis = new BufferedInputStream(new FileInputStream(file));
            ProgressMonitorInputStream pmis = new ProgressMonitorInputStream(
                  ProgressBarDemo.this,
                  "Reading... " + file.getAbsolutePath(),
                  bis);

            pmis.getProgressMonitor().setMillisToPopup(10);
            baos = new BufferedOutputStream(new FileOutputStream("/Users/mypath/Desktop/NewWirelessDiagnostics.tar.gz"));

            byte[] buffer = new byte[2048];
            int nRead = 0;

            while((nRead = pmis.read(buffer)) != -1) {
               baos.write(buffer, 0, nRead);
            }

            pmis.close();
            baos.flush();
            baos.close();
         } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
         } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
         }
      }

      @Override
      protected Void doInBackground() throws Exception {
         // TODO Auto-generated method stub
         copyFile();
         return null;
      }

      @Override
      protected void done() {
         button.setEnabled(true);
      }
   }
}

public class TestProj {

   public static void main(String[] args) {
      ProgressBarDemo demo = new ProgressBarDemo();
      demo.go();
   }
}

有什么建议么?

4

2 回答 2

5

您是copyFile从事件调度线程的上下文中调用的,这意味着 EDT 在方法返回之前无法响应新事件或绘制请求。

尝试将调用放在它自己的Thread上下文中......

Thread t = new Thread(new Runnable(
    public void run() {
        copyFile();
    }
));
t.start();

同样,您可以使用 a SwingWorker,这有点矫枉过正,但是您可以从PropertyChangeListeneror 它的done方法中受益JButton,如果您想防止人们在复制操作时单击按钮进行中

有关更多详细信息,请参阅SwingWorker 线程和 SwingWorker中的并发

更新了示例

跨本地磁盘复制 371mb 文件...

复制

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.ProgressMonitorInputStream;
import javax.swing.SwingWorker;

public class ProgressBarDemo extends JFrame {

    private static final long serialVersionUID = 1L;

    private JButton button;

    ProgressBarDemo() {
        button = new JButton("Click me!");
        ButtonActionListener bal = new ButtonActionListener();
        button.addActionListener(bal);

        this.getContentPane().add(button);
    }

    public void go() {

        this.setLocationRelativeTo(null);
        this.setVisible(true);
        this.pack();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private void copyFile() {

        File file = new File("...");

        BufferedInputStream bis;
        BufferedOutputStream baos;
        try {
            bis = new BufferedInputStream(new FileInputStream(file));
            ProgressMonitorInputStream pmis = new ProgressMonitorInputStream(
                            this,
                            "Reading... " + file.getAbsolutePath(),
                            bis);

            pmis.getProgressMonitor().setMillisToPopup(10);
            baos = new BufferedOutputStream(new FileOutputStream("..."));

            byte[] buffer = new byte[2048];
            int nRead = 0;

            while ((nRead = pmis.read(buffer)) != -1) {
                baos.write(buffer, 0, nRead);
            }

            pmis.close();
            baos.flush();
            baos.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private class ButtonActionListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {

            button.setEnabled(false);
            SwingWorker worker = new SwingWorker() {

                @Override
                protected Object doInBackground() throws Exception {
                    copyFile();
                    return null;
                }

                @Override
                protected void done() {
                    button.setEnabled(true);
                }

            };

            worker.execute();
        }

    }

    public static void main(String[] args) {
        ProgressBarDemo demo = new ProgressBarDemo();
        demo.go();
    }
}

请记住,设置窗口和显示需要考虑开销。系统可能“想要”显示一个窗口,但是当系统设置并准备显示它时, steam可能已经完成复制...

扩展示例

nb:我不太喜欢ProgressMonitorAPI,因为我无法找到 UI 与 EDT 同步的位置,这可能会导致 Java 7 和 8 出现问题

你可以将这个想法正式化为一个自给自足的工人,例如......

public class CopyWorker extends SwingWorker {

    private File source;
    private File dest;
    private Component parent;

    private ProgressMonitorInputStream pmis;

    public CopyWorker(Component parent, File source, File dest) {
        this.parent = parent;
        this.source = source;
        this.dest = dest;
    }

    @Override
    protected Object doInBackground() throws Exception {
        try (InputStream is = new FileInputStream(source)) {
            try (OutputStream os = new FileOutputStream(dest)) {
                pmis = new ProgressMonitorInputStream(
                        parent,
                        "Copying...",
                        is);

                pmis.getProgressMonitor().setMillisToPopup(10);

                byte[] buffer = new byte[2048];
                int nRead = 0;

                while ((nRead = pmis.read(buffer)) != -1) {
                    os.write(buffer, 0, nRead);
                }
            }
        }
        return null;
    }

    @Override
    protected void done() {
        try {
            pmis.close();
        } catch (Exception e) {
        }
    }

}

这试图包含功能,但也处理方法ProgressMonitorInputStream内的清理done,确保它在 EDT 内完成。我会亲自附加一个PropertyChangeListener并监视done属性以确定工作人员何时完成并检查返回结果以获取任何异常,这使您能够以自己的方式处理异常并解耦来自您的流程的工人

于 2014-10-16T01:19:00.763 回答
0

您的程序在文件上工作,但是当涉及到服务器和客户端流时,它会失败。

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Socket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.ProgressMonitorInputStream;
import javax.swing.SwingWorker;

public class FileReceive extends JFrame {
    private static final long serialVersionUID = 1L;
    private BufferedInputStream bufferInput;
    private FileOutputStream fout;
    private BufferedOutputStream bufferOutput;
    private Socket client;
    private JButton button;
    private File fileinfo;
    ProgressMonitorInputStream pois;

    FileReceive() {
        setLocationRelativeTo(null);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        receiveFile();
    }

    public static void main(String arg[]) {
        new FileReceive();
    }

    public void receiveFile() {
        try {
            fileinfo=new File(filepath);
            client=new Socket("localhost",9090);
            fout=new FileOutputStream(fileinfo);
            bufferOutput=new BufferedOutputStream(fout);
            bufferInput=new BufferedInputStream(client.getInputStream());
            pois=new ProgressMonitorInputStream(this, "reading", bufferInput);
            int ch;
            byte[] b=new byte[2048];
            System.out.println("Receiving File");

            while(-1!=(ch=pois.read(b))) {
                bufferOutput.write(b,0,ch);
            }

            pois.close();
            bufferInput.close();
            bufferOutput.close();
            fout.close();
            client.close();
        } catch (IOException e) {
            JOptionPane.showMessageDialog(null, e.getMessage());
        } 
    }
}
于 2018-09-05T18:18:07.023 回答