2012-07-06 7 views
10

を待っている:ここでは、次のコードを検討してください複数SwingWorkers

import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.lang.reflect.InvocationTargetException; 
import javax.swing.*; 

public class TestApplet extends JApplet 
{ 
    @Override 
    public void init() 
    { 
     try 
     { 
      SwingUtilities.invokeAndWait(new Runnable() 
      { 
       @Override 
       public void run() 
       { 
        createGUI(); 
       } 
      }); 
     } 
     catch(InterruptedException | InvocationTargetException ex) 
     { 
     } 
    } 

    private void createGUI() 
    { 
     getContentPane().setLayout(new FlowLayout()); 
     JButton startButton = new JButton("Do work"); 
     startButton.addActionListener(new ActionListener() 
     { 
      @Override 
      public void actionPerformed(ActionEvent ae) 
      { 
       JLabel label = new JLabel(); 
       new Worker(label).execute(); 
      } 
     }); 
     getContentPane().add(startButton); 
    } 

    private class Worker extends SwingWorker<Void, Void> 
    { 
     JLabel label; 

     public Worker(JLabel label) 
     { 
      this.label = label; 
     } 

     @Override 
     protected Void doInBackground() throws Exception 
     { 
      // do work 
      return null; 
     } 

     @Override 
     protected void done() 
     { 
      getContentPane().remove(label); 
      getContentPane().revalidate(); 
     } 
    } 
} 

こと(パブリッシュ/プロセスの方法を使用して)ワーカースレッドのいくつかの中間結果を表示するアプレットにラベルを追加することです。最後に、アプレットのペインからラベルが削除されます。私の質問は、どのように私は独自のワーカースレッドを持つラベルをいくつか作成し、それらがすべて完了したら削除することですか?

ありがとうございます。

UPDATE:

私はこれは私の質問を明確に願っています。私は、すべての労働者が作業を終えた直後に、一度にすべての労働者を取り除いた後ではなく、一度にすべての労働者を取り除きたいと思います。

UPDATE 2:

次のコードで、私は必要なものをやっているようです。私が正しいかどうかをコメントしてください。何か間違っていると感じています。 1つの問題は、ボタンの右側のラベルが削除されても表示されたままであることです。 setVisible(false)はこの問題を解決するようです。それはそれを行う方法ですか?

import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.lang.reflect.InvocationTargetException; 
import java.util.LinkedList; 
import java.util.List; 
import java.util.Queue; 
import java.util.Random; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import javax.swing.*; 

public class TestApplet extends JApplet 
{ 
    private Queue<JLabel> labels = new LinkedList<>(); 
    private static final Random rand = new Random(); 

    @Override 
    public void init() 
    { 
     try 
     { 
      SwingUtilities.invokeAndWait(new Runnable() 
      { 
       @Override 
       public void run() 
       { 
        createGUI(); 
       } 
      }); 
     } 
     catch(InterruptedException | InvocationTargetException ex){} 
    } 

    private void createGUI() 
    { 
     getContentPane().setLayout(new FlowLayout()); 
     JButton startButton = new JButton("Do work"); 
     startButton.addActionListener(new ActionListener() 
     { 
      @Override 
      public void actionPerformed(ActionEvent ae) 
      { 
       ExecutorService executor = Executors.newFixedThreadPool(10); 
       for(int i = 0; i < 10; i++) 
       { 
        JLabel label = new JLabel(); 
        getContentPane().add(label); 
        executor.execute(new Counter(label)); 
       } 
      } 
     }); 
     getContentPane().add(startButton); 
    } 

    private class Counter extends SwingWorker<Void, Integer> 
    { 
     private JLabel label; 

     public Counter(JLabel label) 
     { 
      this.label = label; 
     } 

     @Override 
     protected Void doInBackground() throws Exception 
     { 
      for(int i = 1; i <= 100; i++) 
      { 
       publish(i); 
       Thread.sleep(rand.nextInt(80)); 
      } 

      return null; 
     } 

     @Override 
     protected void process(List<Integer> values) 
     { 
      label.setText(values.get(values.size() - 1).toString()); 
     } 

     @Override 
     protected void done() 
     { 
      labels.add(label); 

      if(labels.size() == 10) 
      { 
       while(!labels.isEmpty()) 
        getContentPane().remove(labels.poll()); 

       getContentPane().revalidate(); 
      } 
     } 
    } 
} 
+0

また、リスト( 'JList')でそれらを置くことを検討してください。 –

+0

@AndrewThompson、はい、しかし、それらを待つコードはどこに置くべきですか?いくつか他のものを産んでいる別のSwingWorkerでなければなりませんか? – Vlad

+0

例外を飲み込まないでください。 – trashgod

答えて

14

すべてのワーカーが作業を完了したら、すべてのラベルを削除する予定です。

hereのように、CountDownLatchはこの文脈でうまくいきます。下の例では、各ワーカーは完了時にlatch.countDown()を呼び出し、Supervisorワーカーはすべてのタスクが完了するまでlatch.await()にブロックします。デモンストレーションの目的で、Supervisorはラベルを更新します。コメントに表示されている卸売業者の取外しは、技術的には可能ですが一般的には魅力的ではありません。代わりに、JListまたはJTableと考えてください。

Worker Latch Test

import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.util.LinkedList; 
import java.util.List; 
import java.util.Queue; 
import java.util.Random; 
import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import javax.swing.*; 

/** 
* @see https://stackoverflow.com/a/11372932/230513 
* @see https://stackoverflow.com/a/3588523/230513 
*/ 
public class WorkerLatchTest extends JApplet { 

    private static final int N = 8; 
    private static final Random rand = new Random(); 
    private Queue<JLabel> labels = new LinkedList<JLabel>(); 
    private JPanel panel = new JPanel(new GridLayout(0, 1)); 
    private JButton startButton = new JButton(new StartAction("Do work")); 

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

      @Override 
      public void run() { 
       JFrame frame = new JFrame(); 
       frame.setTitle("Test"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new WorkerLatchTest().createGUI()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    @Override 
    public void init() { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       add(new WorkerLatchTest().createGUI()); 
      } 
     }); 
    } 

    private JPanel createGUI() { 
     for (int i = 0; i < N; i++) { 
      JLabel label = new JLabel("0", JLabel.CENTER); 
      label.setOpaque(true); 
      panel.add(label); 
      labels.add(label); 
     } 
     panel.add(startButton); 
     return panel; 
    } 

    private class StartAction extends AbstractAction { 

     private StartAction(String name) { 
      super(name); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
       startButton.setEnabled(false); 
       CountDownLatch latch = new CountDownLatch(N); 
       ExecutorService executor = Executors.newFixedThreadPool(N); 
       for (JLabel label : labels) { 
        label.setBackground(Color.white); 
        executor.execute(new Counter(label, latch)); 
       } 
       new Supervisor(latch).execute(); 
     } 
    } 

    private class Supervisor extends SwingWorker<Void, Void> { 

     CountDownLatch latch; 

     public Supervisor(CountDownLatch latch) { 
      this.latch = latch; 
     } 

     @Override 
     protected Void doInBackground() throws Exception { 
      latch.await(); 
      return null; 
     } 

     @Override 
     protected void done() { 
      for (JLabel label : labels) { 
       label.setText("Fin!"); 
       label.setBackground(Color.lightGray); 
      } 
      startButton.setEnabled(true); 
      //panel.removeAll(); panel.revalidate(); panel.repaint(); 
     } 
    } 

    private static class Counter extends SwingWorker<Void, Integer> { 

     private JLabel label; 
     CountDownLatch latch; 

     public Counter(JLabel label, CountDownLatch latch) { 
      this.label = label; 
      this.latch = latch; 
     } 

     @Override 
     protected Void doInBackground() throws Exception { 
      int latency = rand.nextInt(42) + 10; 
      for (int i = 1; i <= 100; i++) { 
       publish(i); 
       Thread.sleep(latency); 
      } 
      return null; 
     } 

     @Override 
     protected void process(List<Integer> values) { 
      label.setText(values.get(values.size() - 1).toString()); 
     } 

     @Override 
     protected void done() { 
      label.setBackground(Color.green); 
      latch.countDown(); 
     } 
    } 
} 
+0

偉大な例、良いこと – mKorbel

+0

ありがとうございました! – Vlad

+1

あなたは大歓迎です。このようなハイブリッドアプレット/アプリケーションは、[ここ](https://sites.google.com/site/drjohnbmatthews/subway)に示すように[tag:java-web-start]を使用してさまざまなデプロイメントオプションを提供します。 – trashgod

1

あなたが持っているコードは、すでにある程度それを行っています。ボタンをクリックすると実際にラベルをコンテンツペインに追加する必要があります。このような何か:

JLabel label = new JLabel(); 
getContentPane().add(label); 
getContentPane().validate(); 
new Worker(label).execute(); 

それが画面に追加されたときに、あなたが実際にそれを見るように、ラベルにテキストを置くために良いアイデアかもしれません。あなたには、いくつかのタスクが実行されているとしてラベルを更新するためにいくつかのコードを追加することができますdoInBackground()メソッドで

JLabel label = new JLabel("Hello...I am here"); 

そして最後に:

for(int i = 0;i < 100; i++){ 
      Thread.sleep(20); 
      label.setText("Counting..." + i); 
    } 

あなたが実際に実行中のタスクを参照してください。この方法。ボタンを複数回クリックすると、複数のラベルが表示され、タスクが完了するとラベルが消えます。

+0

迅速な返信をありがとう。ここに貼り付ける前にコードを簡略化しました。ラベルには実際にテキストがあり、内容ペインに追加されます。 :)しかし、提案をありがとう。私は自分の質問をはっきりと述べなかったと思う。私が意図しているのは、すべての作業員が作業を完了したときに、すべてのラベルを削除することです。 – Vlad

関連する問題