2013-03-05 74 views
0

我正在開發一個java應用程序,使用bufferedInputStream保存大文件。 我已經在JDialog中放置了一個進度條,它指示上傳文件的百分比,並且每n秒增加一次。 問題是應用程序無限期地等待關閉對話框,所以它永遠不會退出。 任何人都可以提供幫助嗎?Java上傳百分比進度條線程

這裏是主應用程序的代碼片段:

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(); 
+1

一個忠告:使用不同的線程耗時的工作比一個處理的UI ...... – ppeterka 2013-03-05 08:59:39

+0

如何在兩個溝通?同樣在上面的Netbeans警告我說updateThread.start();不應該在構造函數裏面,我怎麼把它放在外面? – dendini 2013-03-05 09:02:55

+0

查看此示例(http://stackoverflow.com/questions/15199091/progress-bar-java/15199220#15199220) – MadProgrammer 2013-03-05 09:56:36

回答

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(); 
+0

該進程仍然掛起,因爲progressJBar是在Runnable之外創建的,創建時它啓動了一個線程以每秒更新其進展。您的updateThread中的 – dendini 2013-03-05 09:47:23

+0

:而不是直接更新progressBar:在UI線程的回調中執行(使用'SwingUtilities.invokeLater(...)',如我的文章所示)。 – ben75 2013-03-05 09:52:58

+0

我更新了我的問題根據您的解決方案,它的工作原理,但我仍然不確定線程​​t實際上是否總是會停止... – dendini 2013-03-05 10:17:02

3

這將是一個SwingWorker一份理想的工作 - 做上傳的doInBackground,並將它每隔一段時間調用setProgress與最新進展號碼。使用PropertyChangeListener更新進度欄並關閉done中的對話框,兩者都保證在事件處理線程上運行。

在上面鏈接的javadoc中,有一個非常接近您需要的示例。

0

把它全部帶走,並使用javax.swing.ProgressMonitorInputStream.

+0

怎麼樣?這不僅僅是一個回答而是一個評論。 – 2014-05-21 16:27:17