问题
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