Reputation: 919
I made a sample to make the question clear :
public class Worker extends SwingWorker<Integer, Integer> {
private GeneralUserInterface gui;
public Worker(GeneralUserInterface gui){
this.gui = gui;
}
@Override
protected Integer doInBackground() throws Exception {
int someResultToReturn = 10;
for(int i=0; i<100; i++){
Thread.sleep(50);//The Work
publish(i+1);//calls process, which updates GUI
}
return someResultToReturn;
}
@Override
protected void process(List<Integer> values) {
for (Integer val : values) {
gui.updateProgressBar(val);
}
}
}
private void jButtonDoWorkActionPerformed(java.awt.event.ActionEvent evt) {
Worker worker = new Worker(this);
worker.execute();
try {
int resultToGet = worker.get();//Obviously freezes the GUI
} catch (InterruptedException | ExecutionException ex) {}
//NEXT LINE NEEDS THE RESULT TO CONTINUE
}
public void updateProgressBar(int value){
this.jProgressBar1.setValue(value);
}
As you would guess, the call to worker.get() makes the UI unresponsive, which is normal since it waits the thread to finish. How is this kind of problem usually solved ?
Upvotes: 4
Views: 5249
Reputation: 321
a better solution is to provide your SwingWorker with an instance of an interface implemented by your GUI. That way you can have your Worker update the GUI.
public class GUI implements GUI_INTERFACE{
....
new foo(this);
@Override
public void INTERFACE_METHOD(Object info){
//Update Gui variables here.
}
}
For your SwingWorker:
class foo extends SwingWorker{
GUI_INTERFACE int
public foo(GUI_INTERFACE bar){
int=bar
}
}
Upvotes: 0
Reputation: 7952
How is this kind of problem usually solved ?
Normally what you do is override the Swingworker.done()
method. Done is executed in the GUI thread when your background thread is completed. Then you can safely call get without blocking and do whatever you need to do.
Here is one way to do this:
public class Worker extends SwingWorker<Integer, Integer> {
private GeneralUserInterface gui;
// omitted...
@Override
protected Integer doInBackground() throws Exception {
int someResultToReturn = 10;
for(int i=0; i<100; i++){
Thread.sleep(50);//The Work
publish(i+1);//calls process, which updates GUI
}
return someResultToReturn;
}
// omitted...
@Override
protected void done() {
try {
int resultToGet = worker.get();//Obviously freezes the GUI
} catch (InterruptedException | ExecutionException ex) {}
//NEXT LINE NEEDS THE RESULT TO CONTINUE
}
}
private void jButtonDoWorkActionPerformed(java.awt.event.ActionEvent evt) {
Worker worker = new Worker(this);
worker.execute();
}
However this may not be the most convenient design. I find it works best to have the GUI stuff be the public class, then create the swing worker as a non-static inner class. That way the "done" method has easy access to all the GUI private variables.
Upvotes: 6