2012-03-14 7 views
2

관심 영역을 결정한 다음 해당 영역의 객체를 인식하는 두 가지 주요 단계가있는 프로그램을 작성하고 있습니다. 내 인터페이스에는 단일 JProgressBar가 있으며 현재 작업중인 단계를 나타내려고합니다. 간단한 "선형"접근 방식으로 두 번째 메시지 만 표시된다는 것을 알았습니다. 따라서 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..."); 

에 전화 사이에 일시 정지는 코드가없는 (도가 있어야한다)을 이해한다 두 번째 코드 비트를 완료하고 도달하고 두 백그라운드 작업이 동시에 발생할 가능성이 있습니다. 이 문제를 해결하기 위해

옵션은 다음과 같습니다

  • 이 JProgressBars, 각 작업에 대해 하나를 사용
  • 또는
  • 모두가 같은 백그라운드 스레드 및 실행에서 수행 할 수 있도록 하나의 SwingWorker의 내에서 두 작업을 실행 순차적으로
  • 또는 첫 번째 작업의 속성 변경 수신기에서 첫 번째 작업이 완료되었음을 알린 후 두 번째 작업을 실행합니다 (state 속성은 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(); 
    } 

편집 :
모든 위의 코드는 이미 이벤트 스레드에서 때문에 이벤트 스레드에서 JProgressBar#setString(...) 방법을 대기 할 필요가 없다는 것을 주 , EDT. 현재 코드가 EDT 나 다른 몇 가지 특수한 상황에서 호출 될 때만 필요합니다 (이 코드는 그 중 하나가 아닙니다).

그래서 코드는 다음과 같이하는 것이 좋습니다 것 :

 // ** 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(); 
       } 
관련 문제