setString для JProgressBar более одного раза

Я пишу программу, состоящую из двух основных фаз: определение области интереса и затем распознавание объектов в этой области. В моем интерфейсе есть один JProgressBar, и я хочу, чтобы он указывал, на каком этапе он сейчас работает. Я заметил, что при простом «линейном» подходе отображается только второе сообщение. Итак, после 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();
    }
}

Однако это не работает — в тексте индикатора выполнения остается только «Сегментация».

Я уже пробовал использовать EventQueue вместо SwingUtilities, но безрезультатно. Итак, как мне это сделать?


person skytreader    schedule 14.03.2012    source источник


Ответы (1)


Вы должны понимать, что в коде нет паузы (и не должно быть) между вашим вызовом

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

и к

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

за исключением миллисекунд, необходимых для завершения первого бита кода и достижения второго бита кода, и обе фоновые задачи, вероятно, выполняются одновременно.

Варианты решения этой проблемы включают в себя:

  • Используя два JProgressBars, по одному для каждой задачи,
  • или запуск обеих задач из одного SwingWorker, чтобы обе задачи можно было выполнять в одном и том же фоновом потоке и запускать последовательно,
  • или запуск второй задачи после того, как прослушиватель изменения свойства первой задачи сообщит вам, что первая задача завершена (свойство состояния возвращает SwingWorker.StateValue.DONE).

e.g.,

  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();
              }
person Hovercraft Full Of Eels    schedule 14.03.2012