我从ftp下载文件 
现在需要显示进度条  由于是一个线程 进度条每次都没有同步显示 直接白板 现在需要多线程实现 求教
就是因为进度条在等待 等文件全部现在完后 才显示最后一条信息的进度。。 应该是每下载一个文件就需要该进度条更新一次
因为ftp上有很多文件 每次遍历文件的时候才下载 不可能每次都new一个新的线程  求教如何做到在一个for循环内一边下载 一边更新进度条显示进度  求高手指教

解决方案 »

  1.   


    你需要确保的第一件事:  ftp文件下载这件事,不是在UI线程(EDT)中进行的更新 ProgressBar 的问题,很简单,写一个 adapter,使其能从任何线程调用,其功能就是更新 ProgressBar 的显示。对用户代码(即对你ftp文件下载的代码)的接口可以写成这样:
    public interface ProgressMonitor {
      
      public void updateMessage(String message);  public void updateProgress(int current, int total);
    }
    为了使用方便,也可以加两条显示用的:public void show();public void dispose();
      

  2.   

    文件下载可以用一个单线程运行,循环调用类似这样的方法:
    void download(String filepath, ProgressViewer viewer) {  viewer.updateMessage("Downloading " + filepath + " ... ");    int total = getFileSize(filepath);
      int progress = 0;
      // 在过程中可以调用:
      progress += bufferSize;
      viewer.updateProgress(progress, total);
    }
      

  3.   

    我ftp下载用的是ftp4j这个jar包  看有人实现过该进度条 
    用了工具类 如下
        private static final long serialVersionUID = 1L;    public int total = 0;    public int current = 0;    private JPanel jContentPane = null;    private JLabel jlb = null;    private JProgressBar jpg1 = null;    private JProgressBar jpg2 = null;    /**
         * @param owner
         */
        public Monitor() {
            initialize();
        }    public void setText(String text) {
            jlb.setText(text);
        }    /**
         * This method initializes this
         * 
         * @return void
         */
        private void initialize() {
            this.setSize(300, 200);
            this.setResizable(false);
            this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            this.setTitle("Transms3 AutoUpdater Version 0.1");
            this.setContentPane(getJContentPane());
            this.setLocationRelativeTo(null);
            this.setAlwaysOnTop(true);
            this.setVisible(true);
        }
        
        public static void main(String args[])
        {
         Monitor m = new Monitor();
        }    /**
         * This method initializes jContentPane
         * 
         * @return javax.swing.JPanel
         */
        private JPanel getJContentPane() {
            if (jContentPane == null) {
                jlb = new JLabel();
                jlb.setHorizontalAlignment(SwingConstants.CENTER);
                jlb.setForeground(Color.blue);
                jlb.setHorizontalTextPosition(SwingConstants.CENTER);
                GridLayout gridLayout = new GridLayout();
                gridLayout.setRows(3);
                jContentPane = new JPanel();
                jContentPane.setLayout(gridLayout);
                jContentPane.add(jlb, null);
                jContentPane.add(getJpg1(), null);
                jContentPane.add(getJpg2(), null);
            }
            return jContentPane;
        }    /**
         * This method initializes jpg1
         * 
         * @return javax.swing.JProgressBar
         */
        protected JProgressBar getJpg1() {
            if (jpg1 == null) {
                jpg1 = new JProgressBar();
                jpg1.setStringPainted(true);
                jpg1.setString("总更新文件进度");
            }
            return jpg1;
        }    /**
         * This method initializes jpg2
         * 
         * @return javax.swing.JProgressBar
         */
        protected JProgressBar getJpg2() {
            if (jpg2 == null) {
                jpg2 = new JProgressBar();
                jpg2.setStringPainted(true);
                jpg2.setString("当前更新文件进度");
            }
            return jpg2;
        }
    但是我用该类的时候没有实时更新进度条 所以我想是不是线程问题引起的? 求指教!
      

  4.   

    for (String key : remotefiles.keySet()) {
                monitor.total += remotefiles.get(key).size;
            } monitor.getJpg1().setMaximum(monitor.total);
         monitor.setText("开始下载文件" + "...");
         monitor.getJpg1().setString("下载文件:第" + i + "个/共" + remotefiles.size() + "个");
                listener.setFile(remotefiles.get(filename));
                String localfilepath = formatPath4File(nextFilePath
    + File.separator + filename);
     client.download(filename, new File("D://DZXJ_PIC//"+localfilepath), listener);
      

  5.   


    ProgressViewe 写错了 ,应该是  ProgressMonitor
    实现可以这样写(没有测试):import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.GridLayout;
    import javax.swing.JDialog;
    import javax.swing.JLabel;
    import javax.swing.JProgressBar;
    import javax.swing.SwingUtilities;
    /**
     *
     * @date   31/10/2012
     */
    public class ProgressAdapter implements ProgressMonitor {
      
      private JDialog dialog;
      private JProgressBar bar;
      private JLabel label;
      
      public ProgressAdapter(String title, Component parent) {
        
        assert SwingUtilities.isEventDispatchThread();
        
        dialog = new JDialog();
        dialog.setModal(true);
        dialog.setTitle(title);
        dialog.setLocationRelativeTo(parent);
        
        bar = new JProgressBar();
        label = new JLabel();
        
        dialog.getContentPane().setLayout(new GridLayout(2, 1));
        dialog.getContentPane().add(bar);
        dialog.add(label);
        
        dialog.getContentPane().setPreferredSize(new Dimension(600, 100));
      }
      
      public void show() {
        
        SwingUtilities.invokeLater(new Runnable() {      @Override
          public void run() {
            
            dialog.setVisible(true);
          }
        });
      }
      
      public void dispose() {
        
        SwingUtilities.invokeLater(new Runnable() {      @Override
          public void run() {
            
            dialog.dispose();
          }
        });
      }
      
      @Override
      public void updateProgress(final int current, final int total) {
        
        SwingUtilities.invokeLater(new Runnable() {      @Override
          public void run() {
            
            bar.setMinimum(total);
            bar.setValue(current);
          }
        });
      }  @Override
      public void updateMessage(final String message) {
        
        SwingUtilities.invokeLater(new Runnable() {      @Override
          public void run() {
            
            label.setText(message);
          }
        });
      }
    }
      

  6.   


    bar.setMinimum(total);
    改成bar.setMaximum(total);
      

  7.   

    "你需要确保的第一件事: ftp文件下载这件事,不是在UI线程(EDT)中进行的"这句话是说,假如你的文件下载是因为图形界面的事件引发的,比如 actionPerfromed() 里面触发的,
    那你不能直接开始下载,要确保下载的工作在另一个线程里进行:
    public void actionPerformed(ActionEvent e) {
      
      // 开始下载文件
      new SwingWorker<Void, Void>() {
        
        @Override
        protected Void doInBackground() throws Exception {
          
          // 下载文件
          
          return null;
        }
      }.execute();
    }
      

  8.   

    现在就是由actionPerfromed 触发的 应该如何在另一个线程里运行呢? 这里不太明白
    是在现在的时候 还是?
      

  9.   


    actionPerfromed 这个方法,是在UI线程中被调用的,UI线程的名字叫EDT,是一个单线程,这个线程负责所有的UI控件绘制工作,也就是说,如果你的文件下载工作占用了这个线程,那你整个的图形界面是不可能有任何更新的,就像死机一样。建议你去读一下 SwingWorker 的用法。
      

  10.   


    上班时上不了qq,下班用站内短信发给你qq号