2

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

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

1 に答える 1

4

との呼び出しの間にコードに一時停止がないことを理解する必要があります(また、一時停止するべきではありません)。

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

とに

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

コードの最初のビットが完了してコードの2番目のビットに到達するのに必要なミリ秒を除いて、両方のバックグラウンドタスクが同時に発生している可能性があります。

これを解決するためのオプションは次のとおりです。

  • タスクごとに1つずつ、2つのJProgressBarを使用します。
  • または、単一のSwingWorker内から両方のタスクを実行して、両方を同じバックグラウンドスレッドで実行し、順番に実行できるようにします。
  • または、最初のタスクのプロパティ変更リスナーが最初のタスクが完了したことを通知した後に2番目のタスクを実行すると(状態プロパティはSwingWorker.StateValue.DONEを返します)。

例えば、

  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();
  }

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

したがって、コードは次のようになります。

     // ** 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();
              }
于 2012-03-14T20:01:14.827 に答える