0

Below is a SwingWorker instance that did not update the Java GUI as I had expected it to.

The SwingWorker is implemented inside an action listener for a button. The min and max which define the loop are both a "final int" which are local to the action listener.

The SwingWorker is supposed to on each iteration call the NQueens object's go() method which recursively finds all the solutions for n-queens. Then the NQueens object's toString() is called after which the String is published so that the process() method will update the jProgressBar and the jTextArea. However nothing occurs when the button is pressed. Is this how I should be implementing an intensive process coupled with GUI component updates?

new SwingWorker <Void,String>()
{       
     private int totalPercent;
     @Override
     protected Void doInBackground()
     {
         int diff = max - min + 1;
         int percent = 100;
         if(diff != 0)
         {
              percent = 100/diff;
         }
         totalPercent = 0;
         NQueens queens = new NQueens(min);
         for(int j = min; j <= max; j++)
         {
              queens.go();
              totalPercent += percent;
              String newText = queens.toString();
              publish(newText);
              queens.nextSet();
         }

         isCalced = true;

         return null;
      }

      protected void process(String results)
      {
           jTextArea2.append(results);
           jProgressBar1.setValue(totalPercent);
           jProgressBar1.repaint();
      }                                 
  }.execute();  
MByD
  • 135,866
  • 28
  • 264
  • 277
509dave16
  • 31
  • 5
  • [How to use Progress Bars](http://docs.oracle.com/javase/tutorial/uiswing/components/progress.html) – oers May 09 '12 at 11:54
  • Looks ok to me. Do you know if it is calling the process() at all ? Maybe add some simple System.out debugging? Also try overriding done() and calling get() inside that, it will make any exceptions that happened during doInBackground() get "re-thrown". – Jim May 10 '12 at 15:36

1 Answers1

0

Could the reason be that you've not implemented the right process method? I believe the correct signature of process would be

process(List<String> results) {
  for(String result : results) {
    jTextArea2.append(result);
  }
}

With regards to updating the progressbar; the doInBackground method runs in a separate thread while the process method runs on the thread you invoked the worker from. You should not write to the totalPercent variable from doInBackground and read it from process(). See thread visibility for more on this. Instead, create something like a class called ProgressUpdateEvent which can hold a percent value and a message. That way, you could do as follows :

new SwingWorker <Void,ProgressUpdateEvent>() {

  protected Void doInBackground() {
    for (int i = 0; i <= 100; i++) {
      publish(new ProgressUpdateEvent("At " + i + "% right now", i);
    }
  }

  protected void process(List<ProgressUpdateEvent> events) {
    for (ProgressUpdateEvent event : events) {
      jTextArea2.append(event.getMessage());
      jProgressBar1.setValue(event.getPercent());
    }
  }
}
sbrattla
  • 5,274
  • 3
  • 39
  • 63