2012-03-14 7 views
2

私は2つの主要な段階を持つプログラムを書いています:関心領域の決定とその領域内のオブジェクトの認識です。私のインターフェイスには単一のJProgressBarがあり、現在どのフェーズで作業しているかを示したいと思っています。私は、単純な「線形」アプローチでは、2番目のメッセージだけが表示されることに気付きました。したがって、https://stackoverflow.com/a/277048に続いて、私はRunnablesとSwingUtilities.invokeLaterを使ってプログレスバーの文字列を設定します。JProgressBarのsetStringを複数回

private class MarkListener implements ActionListener { 
    public void actionPerformed(ActionEvent ae) { 
     mainFrame.getGlassPane().setCursor(new Cursor(Cursor.WAIT_CURSOR)); 
     recognitionProgress.setStringPainted(true); 
     BlueMarkerTask bmt = new BlueMarkerTask(); 
     bmt.addPropertyChangeListener(PrismRunnable.this); 

     SwingUtilities.invokeLater(new Runnable(){ 
      public void run(){ 
       recognitionProgress.setString("Marking ROI..."); 
      } 
     }); 

     bmt.execute(); 

     RecognitionTask rt = new RecognitionTask(); 
     rt.addPropertyChangeListener(PrismRunnable.this); 

     SwingUtilities.invokeLater(new Runnable(){ 
      public void run(){ 
       recognitionProgress.setString("Segmenting..."); 
      } 
     }); 

     rt.execute(); 
    } 
} 

ただし、これは機能しません。「セグメンテーション」のみがプログレスバーのテキストに残ります。

私はSwingUtilitiesの代わりにEventQueueを使用しようとしましたが、役に立たなかった。だから、私はこれについてどうやって行くのですか?

答えて

4

あなたは、コードには、一時停止がないことを理解しなければなりません(でもあるはずです)

recognitionProgress.setString("Marking ROI..."); 

と最初のビットのために要した時間(ミリ秒)を除く

recognitionProgress.setString("Segmenting..."); 

までにお電話間両方のバックグラウンドタスクが同時に発生する可能性があります。これを解決する

オプション:

  • 2 JProgressBars、各タスクのいずれかを使用して、
  • 又は
  • 両方が同じバックグラウンドスレッドと実行で行うことができるように、単一のSwingWorkerの中から両方のタスクを実行します最初のタスクが完了したことを通知する(2番目のタスクはStateプロパティがSwingWorker.StateValue.DONEを返す)ことを通知した後に2番目のタスクを実行します。

例えば、

public void actionPerformed(ActionEvent ae) { 
    mainFrame.getGlassPane().setCursor(new Cursor(Cursor.WAIT_CURSOR)); 
    recognitionProgress.setStringPainted(true); 
    BlueMarkerTask bmt = new BlueMarkerTask(); 
    bmt.addPropertyChangeListener(PrismRunnable.this); 

    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      recognitionProgress.setString("Marking ROI..."); 
     } 
    }); 

    bmt.addPropertyChangeListener(new PropertyChangeListener() { 

     @Override 
     public void propertyChange(PropertyChangeEvent pcEvt) { 
      if (pcEvt.getPropertyName().equals("state")) { 
       if (pcEvt.getNewValue().equals(SwingWorker.StateValue.DONE)) { 
       // you'd probably have this in a method. 
       RecognitionTask rt = new RecognitionTask(); 
       rt.addPropertyChangeListener(PrismRunnable.this); 

       SwingUtilities.invokeLater(new Runnable() { 
        public void run() { 
         recognitionProgress.setString("Segmenting..."); 
        } 
       }); 

       rt.execute(); 
       } 
      } 
     } 
    }); 

    bmt.execute(); 
    } 

編集:
上記のすべてのコードが既にでのイベントスレッドであるため、イベントスレッド上JProgressBar#setString(...)方法をキューイングする必要は、ありませんことを注意、EDTこれは、現在のコードがEDTから呼び出されている場合、または他のいくつかの特殊な状況(これは1つではありません)で呼び出されている場合にのみ必要です。

だからあなたのコードは次のように見て良いだろう。

 // ** no need to queue this on the event thread. 
    // ** we're already IN the event thread! 
    recognitionProgress.setString("Marking ROI..."); 

    bmt.addPropertyChangeListener(new PropertyChangeListener() { 

     @Override 
     public void propertyChange(PropertyChangeEvent pcEvt) { 
      if (pcEvt.getPropertyName().equals("state")) { 
       if (pcEvt.getNewValue().equals(SwingWorker.StateValue.DONE)) { 
       // you'd probably have this in a method. 
       RecognitionTask rt = new RecognitionTask(); 
       rt.addPropertyChangeListener(PrismRunnable.this); 

       // ** no need to queue this on the event thread. 
       // ** we're already IN the event thread! 
       recognitionProgress.setString("Segmenting..."); 

       rt.execute(); 
       }