3
votes

I have a swingworker so that my GUI can remain responsive whilst i do work in the background.

The problem is i need to update the gui at various points (e.g. update a label with program status/info), but i have a lot of processing to do which i can't do all in one huge doInBackground method.

So i instantiate other classes from the doInBackground method to do it, the problem is i can't update the gui except in this SW thread or the EDT.

Note: i have removed unnecessary code for brevity

I want to be able to update the gui from DoWork1 & DoWork2 etc. I have tried passing a reference to the SW swingworker object, but cannot access the publish method presumably because it is protected. I may be able to update the gui using reflection, but anyone using my code wouldn't like that. I did hear someone mention somewhere about using a reverse interface, but there was no example so i have no idea on that one..

Any help would be appreciated, thank you.

public class SW extends SwingWorker<Object, String> {

    private DoWork1 doWork1;
    private DoWork2 doWork2;
    private Iframe frame;

    public SW(Iframe frame, DoWork1 doWork1) {
        this.frame = frame;
        this.doWork1 = doWork1;
        this.doWork2 = new DoWork2();

    }

    @Override
    protected Object doInBackground() {
        doWork1.lotsOfWork("");
        publish("Can write to label from here");
        doWork2.lotsOfWork("", "");
        return null;
    }

    @Override
    public void process(List<String> chunks) {
        for (String s : chunks) {
            frame.getLabel().setText(s);
        }
    }

    @Override
    protected final void done() {
    }
}


public class DoWork1 {
    public DoWork1() {
    }
    private lotsOfWork(String s) {
        //Do lots of work in here
        //But need to update the gui with information!
        //would like to be able to do something like:
        publish("somehow write to label from here!?");
    }
}


public class DoWork2 {
    public DoWork2() {
    }
    private lotsOfWork(String s, String s) {
        //Do lots more work in here
        //But need to update the gui with information!
        //would like to be able to do something like:
        publish("somehow write to label from here!?");
    }
}
2
Rather than publishing from the DoWork* classes, can't you return the result of lotsOfWork and publish in the SW class? - Can't Tell
@Can't Tell There is a lot of operations going on and the idea is to inform the user where the program is every step of the way. - djangocode
I think i have found the solution. If the other classes extend swingworker also and have a process method, and an unused doinbackground method, they can also write/publish to the GUI. - djangocode
Found a better way. In the swingworker create a public method called say publishData that then calls the protected publish method, and access publishData from the other classes DoWork1 etc. - djangocode

2 Answers

2
votes

In the swingworker create a public method called say publishData that then calls the protected publish method, and access publishData from the other classes DoWork1 via a variable or an interface.

This way all the classes instantiated in the dobackground work method can publish data to the EDT/GUI too.

2
votes

I had the same problem, and I'm using a number of different anonymous SwingWorkers. So, I formalized the solution this way:

/**
 * Same as SwingWorker but providing a public publish function
 */
public abstract class MySwingWorker<T, V> extends SwingWorker<T, V> {
    public final void myPublish(V... args) {
        publish(args);
    }
}

I use MySwingWorker instead of SwingWorker for these anonymous classes, and pass the MySwingWorker instance to methods that will need to update the display. It provides a consistent way to do this for a number of rather different SwingWorker classes, even between packages, without having to make the SwingWorker implementations public classes.

I wonder if there is a good reason that publish() is protected. Fortunately, there's an easy workaround.

For an even better answer that addresses a much wider scope closely related to this question, see the answer from Joe Coder to a similar question.