Using Swingworker publish method in another class

自古美人都是妖i 提交于 2019-12-30 07:11:11

问题


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!?");
    }
}

回答1:


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:


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.



来源:https://stackoverflow.com/questions/28135228/using-swingworker-publish-method-in-another-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!