5

hi id like to know whats the best way to add text to a jtextarea from a swingworkerthread, ive created another class which a jbutton calls by Threadsclass().execute(); and the thread runs in parallel fine with this code

public class Threadsclass extends SwingWorker<Object, Object> {


@Override
protected Object doInBackground() throws Exception {
    for(int x = 0; x< 10;x++)
        try {
            System.out.println("sleep number :"+ x);



        Thread.sleep(1000);
    } catch (InterruptedException ex) {
        Logger.getLogger(eftcespbillpaymentsThreads.class.getName()).log(Level.SEVERE, null, ex);
    }
    throw new UnsupportedOperationException("Not supported yet.");
}

}

now what id like to do is add the value of x to the text area on the main gui, any ideas much appreciated.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
user2168435
  • 732
  • 2
  • 10
  • 27
  • 2
    [The javadoc](http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html) has an example doing exactly that: PrimeNumbersTask. – JB Nizet Jun 05 '13 at 10:59

2 Answers2

9

There is an excellent example from the JavaDocs

class PrimeNumbersTask extends
        SwingWorker<List<Integer>, Integer> {

    PrimeNumbersTask(JTextArea textArea, int numbersToFind) {
        //initialize
    }

    @Override
    public List<Integer> doInBackground() {
        List<Integer> numbers = new ArrayList<Integer>(25);
        while (!enough && !isCancelled()) {
            number = nextPrimeNumber();
            numbers.add(number);
            publish(number);
            setProgress(100 * numbers.size() / numbersToFind);
        }

        return numbers;
    }

    @Override
    protected void process(List<Integer> chunks) {
        for (int number : chunks) {
            textArea.append(number + "\n");
        }
    }
}

JTextArea textArea = new JTextArea();
final JProgressBar progressBar = new JProgressBar(0, 100);
PrimeNumbersTask task = new PrimeNumbersTask(textArea, N);
task.addPropertyChangeListener(
 new PropertyChangeListener() {
     public  void propertyChange(PropertyChangeEvent evt) {
         if ("progress".equals(evt.getPropertyName())) {
             progressBar.setValue((Integer)evt.getNewValue());
         }
     }
 });

task.execute();
System.out.println(task.get()); //prints all prime numbers we have got

Take a look at publish and process

The underlying intention is that you need to update the UI from only within the Event Dispatching Thread, by passing the data you want to updated to the UI via the publish method, SwingWorker will call process for you within the context of the EDT

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Not sure why you rejected my edit.. right now the `return numbers;` is outside of the `doInBackground`, and the `protected void process(..) {..}` is outside of the `PrimeNumbersTask` class – Marc Sep 03 '15 at 12:49
  • I've read in the [JavaDoc for get()](https://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html#get()) that `get()` will freeze the GUI / `EDT`. Would this be a problem here? I've also read, that people usually change `done()` and use `get()` in there to avoid the freeze. The example from the JavaDoc page does not address the freeze directly, so this might be overlooked when someone copies the example. – hamena314 Sep 28 '16 at 12:24
  • 1
    @hamena314 Generally, yes, it's a bad idea. The example above actually uses the process method to update the ui, which is called within the EDT – MadProgrammer Sep 28 '16 at 19:44
6

Within doInBackground(), use publish(V... chunks) to send data to process(List<V> chunks).

Community
  • 1
  • 1
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417