Batch-updating JComponents. Need suggestions for a better (threaded) design
I have a GUI in which some groups of JComponents get "batch-updated", i.e., I have a loop and for almost every iteration of the loop, I need to update these JComponents. So, I tried to do the updates alongside the computations in the loop but it didn't go well being that, (if I interpret correctly) the updates were "slowed down" by the computations, the effect being only the last update became perceptible to the user.
That's when I thought of p开发者_C百科utting all update-related code on a separate thread. First off, I created an interface called UpdatableComponent which will wrap all JComponents that must be updated:
public interface UpdatableComponent {
/**
* Implementors should be the one responsible for typecasting update
* into the appropriate objects.
*/
public void update(Object update);
}
So if, for instance, I want to update a JLabel
public class UpdatableJLabel implements UpdatableComponent{
private JLabel l;
public UpdatableJLabel(JLabel l){
this.l = l;
}
public void update(Object update){
l.setText((String) update);
}
}
Then, my Runnable class for threading:
public class UIUpdateRunnable implements Runnable {
private UpdatableComponent[] forUpdating;
public UIUpdateRunnable(UpdatableComponent[] uc) {
forUpdating = uc;
}
public void run() {
int limit = forUpdating.length;
for(int i = 0; i < limit; i++){
}
}
}
And this is where I hit a snag. How do I know what argument to pass for each UpdatableComponent's update method? I thought of maintaining an Object array, arguments, which will map an UpdatableComponent to an argument for its update method (I have a setter method for it, of course). But then that would be (1) too tightly-coupled---bad design!---and (2) too much for a thread; the loop inside run will continuously call update on each UpdatableComponent, giving it its designated argument, updating regardless whether it actually updated or not.
I can't help but feel that I may have missed a simple way to do it. Any suggestion/advice will be very welcome. Thank you.
It sound like a SwingWorker is what you are looking for. The computation is done inside the method doInBackground()
, results are publish()
ed and process()
then updates the components.
this issue has to do with Concurrency in Swing, there is described other basic stuff and including @Howard
+1 suggestion about SwingWorker
for Runnable#Thread
works,
public void update(Object update) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
l.setText((String) update);
}
});
}
精彩评论