Win a copy of Java Concurrency Live Lessons this week in the Threads forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

SwingWorker and Communications with GUI  RSS feed

 
Dave Robbins
Ranch Hand
Posts: 131
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Folks,

I'm writing an app that schedules a list of jobs to be sent to a ray tracer
each job may take an hour or more
so, I have a list of jobs, I want to do them one at a time, not all together
the ray tracer gives info on what it's doing that I'd like to post to the GUI
so I loop through each job and create an instance of my class that extends SwingWorker
I'm using this code as an example

http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html#setProgress(int)

the second example, I'll post the code here for discussion



so far I can get it to post the messages from the ray tracer when it finishes the job but not as it goes along
so I'm here asking for an explanation of the example code and if I understand it correctly
first off, they pass textArea to task in it's constructor and task calls a function on it
I thought having the worker thread do this was a no no
second, what is the purpose of calling



it looks like that fires a PropertyChangeEvent causing the GUI thread to modify the progress bar
third, is the purpose of calling setProgress() to set the value that gets sent to the GUI in the PropertyChangeEvent?
and last, what's up with the overridden function process()?
isn't it writing to the GUI?
didn't we just do that with the publish() function?
sorry, I'm a bit confused here, are they showing me 2 different ways to do things?

Clarification Appreciated
Dave
 
Dave Robbins
Ranch Hand
Posts: 131
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think I'm starting to get it
the process() function runs in the Event Dispatch Thread so it can write to the textArea

Dave
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave Robbins wrote:so far I can get it to post the messages from the ray tracer when it finishes the job but not as it goes along
so I'm here asking for an explanation of the example code and if I understand it correctly
first off, they pass textArea to task in it's constructor and task calls a function on it
I thought having the worker thread do this was a no no


Doing it in the worker thread is a nono. However, the code you posted doesn't do it in the worker thread. The only code that executes in the worker thread is the doInBackground() method. The process(...) method does the textArea updating, and process(...) gets called in the Event Dispatch Thread, where all swing updates should be run.


second, what is the purpose of calling



it looks like that fires a PropertyChangeEvent causing the GUI thread to modify the progress bar

No. The API says:
publish

protected final void publish(V... chunks)

Sends data chunks to the process(java.util.List) method. This method is to be used from inside the doInBackground method to deliver intermediate results for processing on the Event Dispatch Thread inside the process method.

There may be a property change event triggered when publish is called, I don't think so though. That isn't stated. The point is just to add 'value' updates that get collected. Then when the process(...) method gets called those values can be written to the GUI.



third, is the purpose of calling setProgress() to set the value that gets sent to the GUI in the PropertyChangeEvent?

Yes. The setProgress() method does trigger a PropertyChangeEvent because the progress attribute is a bound property. So when you call setProgress(...) you set the SwingWorker's progress attribute, a measure of how far along it has gone. Because the attribute is a bound property, setting its value causes a PropertyChangeEvent to report to any listeners what the new value is.


and last, what's up with the overridden function process()?
isn't it writing to the GUI?
didn't we just do that with the publish() function?


From the API:
# Event Dispatch Thread: All Swing related activities occur on this thread. SwingWorker invokes the process and done() methods and notifies any PropertyChangeListeners on this thread.
- and -
process

protected void process(List<V> chunks)

Receives data chunks from the publish method asynchronously on the Event Dispatch Thread.


So this method gets called on the EDT, where all GUI updates should be executed. Its purpose is to transfer the work done in the background thread and report it to the GUI.


so far I can get it to post the messages from the ray tracer when it finishes the job but not as it goes along


The code snippet you showed is just a snippet, we don't see where or how that code gets executed. I suspect you are calling it from the EDT, so when the code gets to:

it would block the GUI from updating. Or you aren't adding the text area/progress bar to a GUI so you can see what is going on.

 
Dave Robbins
Ranch Hand
Posts: 131
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here's my class that extends SwingWorker



if I give it a task of rendering 25 frames out of an animation it will post the output of the ray tracer back to the GUI after each frame
if I run the same command on the command line it prints out about 20 lines of info for each frame and does it as the frame is being rendered
I'm thinking maybe this is as good as it gets, it is doing 25 updates of the GUI during the time this thread runs

the thing called "job" that I pass to the constructor of my class is an object that knows all about the command to be sent to the ray tracer

Dave
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It could be one of a couple of things

1) It could be that you are using a BufferedReader, and the input is being buffered. Try a different reader or InputStream.
2) It could be that the process buffers the input and it doesn't get full or flushed until the very end. In which case there isn't much you can do.
3) The SwingWorker doesn't process the output each time it is published, but may condense several publishes into a single process() call. So if the publishing happens in quick succession then perhaps it is waiting until it is all done before reporting. If this is important (doesn't sound like it is) you might try a different publishing scheme - such as using SwingUtilities.invokeLater(...).
 
Dave Robbins
Ranch Hand
Posts: 131
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
the ray tracer is multithreaded so it's hammering the cpu despite it being multi core
I can imagine it might wait till it finishes a frame to update
I'll play around with your suggestion on the type of stream, it's ok like it is but "better" is always good

Dave
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!