2017-08-09 33 views
1

我想監視從源文件複製到目標文件的進度。我已經使用​​關鍵字,但不知怎的,它不像我期望的那樣工作,我的邏輯可能是錯誤的。如果你幫助我,我會很高興。 這是我的代碼。用jProgressBar同步複製顯示

public class Download extends javax.swing.JFrame { 
    int val=0; 
    private Timer t; 
    private ActionListener a; 

/* Creates new form Download */ 
    public Download() { 
     initComponents(); 
     jProgressBar1.setValue(val); 
     a = new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
      if (jProgressBar1.getValue() < val) 
       jProgressBar1.setValue(jProgressBar1.getValue()+1); 
      else 
       t.stop(); 
      }   
     }; 
    } 
    public synchronized void copy(String source,String url) 
    { 
     try {  
     val+=25; 
     t=new Timer(200,a); 
     t.start(); 
     FileInputStream fs = new FileInputStream(source); 
     FileOutputStream os = new FileOutputStream(url); 
     int b; 
     while ((b = fs.read()) != -1) { 
      os.write(b); 
     } 
     os.close(); 
     fs.close(); 
     } catch (Exception E) { 
     E.printStackTrace(); 
     }   
    } 

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {           
     JFileChooser chooser = new JFileChooser(); 
     chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 
     String url = null; 
     int returnValue = chooser.showDialog(null, "Select"); 
     if (returnValue == JFileChooser.APPROVE_OPTION) { 
     url = chooser.getSelectedFile().getPath(); 
     } else { 
     dispose(); 
     } 
     JOptionPane.showMessageDialog(this,"Wait for Completion"); 

     if(CB1.isSelected()==true) 
     { 
     File f = new File(getClass().getResource("/PCycle/Ele.pdf").getFile()); 
     String source= f.getAbsolutePath(); 
     copy(source,(url+"\\"+CB1.getText()+".pdf")); 
     } 
     if(CB2.isSelected()==true) 
     { 
     File f = new File(getClass().getResource("/PCycle/Mech.pdf").getFile()); 
     String source= f.getAbsolutePath(); 
     copy(source,(url+"\\"+CB2.getText()+".pdf")); 
     } 
     if(CB3.isSelected()==true) 
     { 
     File f = new File(getClass().getResource("/PCycle/Phy.pdf").getFile()); 
     String source= f.getAbsolutePath(); 
     copy(source,(url+"\\"+CB3.getText()+".pdf")); 
     } 
     if(CB4.isSelected()==true) 
     { 
     File f = new File(getClass().getResource("/PCycle/Civil.pdf").getFile()); 
     String source= f.getAbsolutePath(); 
     copy(source,(url+"\\"+CB4.getText()+".pdf")); 
     } 

     JOptionPane.showMessageDialog(this,"Completed"); 

     try { 
      jProgressBar1.setValue(100);     
      Thread.sleep(3000); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(Download.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     System.exit(0); 
    } 
} 

在這裏,我試圖執行一個邏輯這樣的,每當我們稱之爲「複製」的方法,將文件從一個位置複製到另一個在此之前,它應該運行的計時器方法,通過它的進展將顯示jProgressBar。但不幸的是,即使在使用​​之後,它也不會顯示每個文件的進度。

+0

您可能需要使用[ProgressMonitorInputStream(https://docs.oracle.com/javase/8/docs/api/javax/swing/ProgressMonitorInputStream.html),其讀出時自動打開一個進度監控從一個流,如果該過程需要一個不平凡的時間量。 – AJNeufeld

回答

1

問題是你阻塞Swing的事件分派線程(EDT)。

當EDT沒有忙於響應事件時,Swing會進行繪圖。在這種情況下,jButton1ActionPerformed在所有文件都被複制之前不會返回。因此,雖然在每個copy()呼叫期間啓動Timer,但定時器永遠不會有機會過期,因爲jButton1ActionPerformed從未返回。

在這種情況下,您希望使用SwingWorker在後臺線程中複製文件。

  • 當你要開始複製文件:
    • 在主線程
    • 創建啓動定時器並開始SwingWorker
    • 打開模型對話框,以阻止進一步的用戶操作(或者禁用UI)
  • 由於計時器到期,你的進度條前進,繪製。
  • SwingWorkerdone()(其在EDT執行),
    • 停止定時器
    • 關閉該對話框(或重新啓用UI)

:不要創建或訪問任何UI項目,或從後臺工作線程創建/啓動/停止計時器。這些操作只能在EDT上執行。


粗糙例如,示出了從操作者禁用UI元素,開始SwingWorker,發佈以顯示進度(其文件將被下載),使UI當工人完成。

使用3秒睡眠僞造文件副本。

package progress; 

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.util.List; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JProgressBar; 
import javax.swing.SwingUtilities; 
import javax.swing.SwingWorker; 
import javax.swing.Timer; 

@SuppressWarnings("serial") 
public class Download extends JFrame { 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(Download::new); 
    } 

    private final JButton downloadBtn = new JButton("Start Download"); 
    private final JProgressBar progressBar = new JProgressBar(); 
    private final Timer timer = new Timer(200, this::timerTick); 

    Download() { 
     super("Download Example"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setSize(400, 300); 
     setLocationByPlatform(true); 

     downloadBtn.addActionListener(this::startDownload); 
     add(downloadBtn, BorderLayout.PAGE_START); 

     progressBar.setStringPainted(true); 
     add(progressBar, BorderLayout.PAGE_END); 

     setVisible(true); 
    } 

    private void startDownload(ActionEvent evt) { 
     downloadBtn.setEnabled(false); 
     timer.start(); 
     DownloadWorker worker = new DownloadWorker("File1", "FileB", "AnotherFile"); 
     worker.execute(); 
    } 

    private void timerTick(ActionEvent evt) { 
     progressBar.setValue(progressBar.getValue()+2); 
    } 

    private class DownloadWorker extends SwingWorker<Void, String> { 

     private final String[] files; 

     DownloadWorker(String ...files) { 
      this.files = files; 

      progressBar.setValue(0); 
     } 

     @Override 
     protected Void doInBackground() throws Exception { 
      for(String file : files) { 
       publish(file); 

       // Copy the file 
       Thread.sleep(3000); // Pretend copy takes a few seconds 
      } 
      return null; 
     } 

     @Override 
     protected void process(List<String> chunks) { 
      String file = chunks.get(chunks.size()-1); // Just last published filename 
      progressBar.setString("Downloading "+file + " ..."); 
     } 

     @Override 
     protected void done() { 
      progressBar.setString("Complete"); 
      progressBar.setValue(100); 
      timer.stop(); 
      downloadBtn.setEnabled(true); // Re-enable UI 
     } 
    } 
} 
+0

謝謝先生。 如果你能儘快提供一個例子,它會更有幫助。 –

+0

已添加示例。希望你能適應你的需求。進度條只是按每個計時器滴答滴答的數量推進,就像您試圖在您的問題示例代碼中進行編碼一樣。理想情況下,您可以查詢工作人員複製的字節數,計算實際的進度百分比等。 – AJNeufeld

+0

謝謝先生,我修改了這些更改,它確實幫助了我。 –