Swingworker - Is it possible?

E

Edsoncv

Hello
Recently I have implemented a swingworker dialog in order to display
a progressbar and some text while some math computations are
happening. It works fine except for one thing: I want a particular
behavior and do not know if it can be handled with swingworker, maybe
the experts can help me:

In my GUI I use a actionPerformed method to start a long task
(Swingworker), in this task I perform some calculations and update my
JprogressBar and a JTextArea. But I want some results to be displayed
right after the task is done(with printSolveMessages()), but if I call
this printing function in the next line it does not print the last
calculation result (in fact the initial value for the variables),
since the calculation is running in another thread. I tried the
swingworker.get() method, but it freezes all the GUI and the
progressbar is not updated. Any clues of how to do that?

The actionperformed class is like this:

public void actionPerformed(ActionEvent evt) {
if (evt.getSource() == startButton){
startButton.setEnabled(false);
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
// task is the swingworker
task.addPropertyChangeListener(this);
task.execute();
/* the task is executing and I want a pause before
print the results with the function below, otherwhise I get
old results*/
printSolveMessages();

I also tried a while(!pMon.isDone()){} right before printSolveMessages
(); but it also locks the screen upate.

pMon is a object that tracks the start and the end of the task.
 
K

Knute Johnson

Edsoncv said:
Hello
Recently I have implemented a swingworker dialog in order to display
a progressbar and some text while some math computations are
happening. It works fine except for one thing: I want a particular
behavior and do not know if it can be handled with swingworker, maybe
the experts can help me:

In my GUI I use a actionPerformed method to start a long task
(Swingworker), in this task I perform some calculations and update my
JprogressBar and a JTextArea. But I want some results to be displayed
right after the task is done(with printSolveMessages()), but if I call
this printing function in the next line it does not print the last
calculation result (in fact the initial value for the variables),
since the calculation is running in another thread. I tried the
swingworker.get() method, but it freezes all the GUI and the
progressbar is not updated. Any clues of how to do that?

The actionperformed class is like this:

public void actionPerformed(ActionEvent evt) {
if (evt.getSource() == startButton){
startButton.setEnabled(false);
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
// task is the swingworker
task.addPropertyChangeListener(this);
task.execute();
/* the task is executing and I want a pause before
print the results with the function below, otherwhise I get
old results*/
printSolveMessages();

I also tried a while(!pMon.isDone()){} right before printSolveMessages
(); but it also locks the screen upate.

pMon is a object that tracks the start and the end of the task.

You are blocking the EDT. You can't do that if you want the GUI to
update. Just start another thread and run printSolveMessages() in that
thread. If it needs to update the GUI then use a SwingWorker for to run
it in.
 
J

John B. Matthews

Knute Johnson said:
You are blocking the EDT. You can't do that if you want the GUI to
update. Just start another thread and run printSolveMessages() in
that thread. If it needs to update the GUI then use a SwingWorker
for to run it in.

Knute's right. If you haven't already seen it, you might look at the
PrimeNumbersDemo application, as an example:

<https://swingworker.dev.java.net/>
 
B

blue indigo

You are blocking the EDT. You can't do that if you want the GUI to
update. Just start another thread and run printSolveMessages() in that
thread. If it needs to update the GUI then use a SwingWorker for to run
it in.

SwingWorker supplies a done() method that it calls on the EDT when it
is done. It is ready-made for this purpose, so the OP can just implement
the done() method in his(?) SwingWorker to update the GUI with this
information when the SwingWorker is done. It can use get(), which
shouldn't block when called from done().

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

Edsoncv

SwingWorker supplies a done() method that it calls on the EDT when it
is done. It is ready-made for this purpose, so the OP can just implement
the done() method in his(?) SwingWorker to update the GUI with this
information when the SwingWorker is done. It can use get(), which
shouldn't block when called from done().

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

Thanks a lot for the sugestions.
Playing a little a found also a different solution. In the property
change listener I did the following:

public void propertyChange(PropertyChangeEvent evt) {
if (pMon.isDone()){
startButton.setEnabled(true);
setCursor(null);
/* Here I only print the results if the progressMonitor is finished,
so it is the last action to be done /*
printSolveMessages();

}
if ("progress" == evt.getPropertyName()) {
int progress = (Integer) evt.getNewValue();
int progressOld = (Integer) evt.getOldValue();
if (progress >= progressOld){
progressBar.setValue(progress);

}
}
}
 
L

Lew

Edsoncv said:
   Playing a little a found also a different solution. In the property
change listener I did the following:

  public void propertyChange(PropertyChangeEvent evt) {
                if (pMon.isDone()){

Your indentation is far too wide for Usenet. Don't use TABs, and
don't indent more than four spaces.
                        startButton.setEnabled(true);
                        setCursor(null);
/* Here I only print the results if the progressMonitor is finished,
so it is the last action to be done /*
                         printSolveMessages();

                }
                if ("progress" == evt.getPropertyName()) {

This equality test will fail, usually. You used the wrong equality
test.
                    int progress = (Integer) evt.getNewValue();
                    int progressOld = (Integer) evt..getOldValue();
                    if (progress >= progressOld){

Strictly speaking, you only need to set a new value on the progress
bar if the new value exceeds the old value; if they're equal there's
not much point in resetting the value.
 
R

Roedy Green

swingworker dialog

see http://mindprod.com/jgloss/swingworker.html

The key thing you must understand is it runs all your code on the EDT
thread. This means you have to be VERY quick. If you dawdle in the
least your entire GUI will freeze.

If you need to do time-consuming tasks, they need to run on some other
threads. see http://mindprod.com/jgloss/thread.html
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Here is a point of no return after which warming becomes unstoppable
and we are probably going to sail right through it.
It is the point at which anthropogenic (human-caused) warming triggers
huge releases of carbon dioxide from warming oceans, or similar releases
of both carbon dioxide and methane from melting permafrost, or both.
Most climate scientists think that point lies not far beyond 2°C (4°F) C hotter."
~ Gwynne Dyer
 
R

RedGrittyBrick

Roedy said:
see http://mindprod.com/jgloss/swingworker.html

The key thing you must understand is it runs all your code on the EDT
thread.

For a moment there I thought "it" referred to "swingworker" in the prior
sentences!

This means you have to be VERY quick. If you dawdle in the
least your entire GUI will freeze.

If you need to do time-consuming tasks, they need to run on some other
threads. see http://mindprod.com/jgloss/thread.html


The API docs for SwingWorker may help also:

"There are three threads involved in the life cycle of a SwingWorker :

Current thread: The execute() method is called on this thread. It
schedules SwingWorker for the execution on a worker thread and returns
immediately. One can wait for the SwingWorker to complete using the get
methods.

Worker thread: The doInBackground() method is called on this
thread. This is where all background activities should happen. To notify
PropertyChangeListeners about bound properties changes use the
firePropertyChange and getPropertyChangeSupport() methods. By default
there are two bound properties available: state and progress.

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."


I usually do slow stuff in doInBackground() and update the GUI in
done(). The former is not executed on the EDT, the latter is.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top