2012-06-26 33 views
1

我想在新的JDialog中創建JProgressBar,女巫將在與主邏輯分離的線程中。所以我可以通過創建新的JDialog開始不確定的進展,並通過處理JDialog來完成這一進程。但它讓我很難實現這一點,因爲在JDialog出現之後,直到主線程(SwingUtilities)中的邏輯完成後才顯示任何組件(包括JProgressBar)。JProgressBar在新線程中JDialog

主題包括的JDialog:

package gui.progress; 

public class ProgressThread extends Thread { 
    private ProgressBar progressBar = null; 

    public ProgressThread() { 
     super(); 
    } 

    @Override 
    public void run() { 
     progressBar = new ProgressBar(null); 
     progressBar.setVisible(true); 
    } 

    public void stopThread() { 
     progressBar.dispose(); 
    } 
} 

的JProgressBar切換方法:

private static ProgressThread progressThread = null; 
... 
public static void toggleProcessBar() { 
    if(progressThread == null) { 
     progressThread = new ProgressThread(); 
     progressThread.start(); 
    } else { 
     progressThread.stopThread(); 
     progressThread = null; 
    } 
} 
+0

不要調用Swing代碼關閉[EDT(http://en.wikipedia.org/wiki/ Event_dispatching_thread)。 – predi

+0

查看[這個答案](http://stackoverflow.com/questions/8916721/java-swing-update-label/8917565#8917565)舉例 – Robin

+0

聽起來像你需要一個[ProgressMonitor](http:// docs。 oracle.com/javase/7/docs/api/javax/swing/ProgressMonitor.html),以及一些[如何使用它的示例](http://docs.oracle.com/javase/tutorial/uiswing/components/ progress.html) –

回答

8

但它給我時間難以實現顯示的JDialog因爲後不顯示,直到主線程(SwingUtilities類的)邏輯的任何組件(包括的JProgressBar)完成。

你有問題與Concurrency in Swing,Swing是單線程的所有更新必須在EventDispatchThread做,有兩種方式

編輯

這段代碼模擬違反EDT和SwingWorker的正確的解決方法太

import java.awt.Dimension; 
import java.awt.Toolkit; 
import java.awt.Window; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 

import javax.swing.*; 

public class TestProgressBar { 

    private static void createAndShowUI() { 
     JFrame frame = new JFrame("TestProgressBar"); 
     frame.getContentPane().add(new TestPBGui().getMainPanel()); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     java.awt.EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       createAndShowUI(); 
      } 
     }); 
    } 

    private TestProgressBar() { 
    } 
} 

class TestPBGui { 

    private JPanel mainPanel = new JPanel(); 

    public TestPBGui() { 
     JButton yourAttempt = new JButton("Your attempt to show Progress Bar"); 
     JButton myAttempt = new JButton("My attempt to show Progress Bar"); 
     yourAttempt.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       yourAttemptActionPerformed(); 
      } 
     }); 
     myAttempt.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       myAttemptActionPerformed(); 
      } 
     }); 
     mainPanel.add(yourAttempt); 
     mainPanel.add(myAttempt); 
    } 

    private void yourAttemptActionPerformed() { 
     Window thisWin = SwingUtilities.getWindowAncestor(mainPanel); 
     JDialog progressDialog = new JDialog(thisWin, "Uploading..."); 
     JPanel contentPane = new JPanel(); 
     contentPane.setPreferredSize(new Dimension(300, 100)); 
     JProgressBar bar = new JProgressBar(0, 100); 
     bar.setIndeterminate(true); 
     contentPane.add(bar); 
     progressDialog.setContentPane(contentPane); 
     progressDialog.pack(); 
     progressDialog.setLocationRelativeTo(null); 
     Task task = new Task("Your attempt"); 
     task.execute(); 
     progressDialog.setVisible(true); 
     while (!task.isDone()) { 
     } 
     progressDialog.dispose(); 
    } 

    private void myAttemptActionPerformed() { 
     Window thisWin = SwingUtilities.getWindowAncestor(mainPanel); 
     final JDialog progressDialog = new JDialog(thisWin, "Uploading..."); 
     JPanel contentPane = new JPanel(); 
     contentPane.setPreferredSize(new Dimension(300, 100)); 
     final JProgressBar bar = new JProgressBar(0, 100); 
     bar.setIndeterminate(true); 
     contentPane.add(bar); 
     progressDialog.setContentPane(contentPane); 
     progressDialog.pack(); 
     progressDialog.setLocationRelativeTo(null); 
     final Task task = new Task("My attempt"); 
     task.addPropertyChangeListener(new PropertyChangeListener() { 

      @Override 
      public void propertyChange(PropertyChangeEvent evt) { 
       if (evt.getPropertyName().equalsIgnoreCase("progress")) { 
        int progress = task.getProgress(); 
        if (progress == 0) { 
         bar.setIndeterminate(true); 
        } else { 
         bar.setIndeterminate(false); 
         bar.setValue(progress); 
         progressDialog.dispose(); 
        } 
       } 
      } 
     }); 
     task.execute(); 
     progressDialog.setVisible(true); 
    } 

    public JPanel getMainPanel() { 
     return mainPanel; 
    } 
} 

class Task extends SwingWorker<Void, Void> { 

    private static final long SLEEP_TIME = 4000; 
    private String text; 

    public Task(String text) { 
     this.text = text; 
    } 

    @Override 
    public Void doInBackground() { 
     setProgress(0); 
     try { 
      Thread.sleep(SLEEP_TIME);// imitate a long-running task 
     } catch (InterruptedException e) { 
     } 
     setProgress(100); 
     return null; 
    } 

    @Override 
    public void done() { 
     System.out.println(text + " is done"); 
     Toolkit.getDefaultToolkit().beep(); 
    } 
} 
+0

+1!好建議。 – GETah

+0

很好的例子,+1 – tenorsax

+0

@Max謝謝,真的是真正的Swing大師之一(在這個論壇上)發佈我similair代碼作爲我的問題的答案(另一個論壇) – mKorbel

1

顯示在主線程(其中所有的擺動的東西是怎麼回事),進度條,並做了密集的背景在一個單獨的線程上工作。

用戶界面一直會響應(因爲您不阻止主線程),並且您可以在長時間運行的任務完成時通知它。

+0

請指定主線程是事件調度線程,因爲應該在該線程上訪問所有Swing組件(與執行主方法的線程不同) – Robin