views:

151

answers:

3

I have an assignment where i have to create an Image Gallery which uses a SwingWorker to load the images froma a file, once the image is load you can flip threw the image and have a slideshow play. I am having trouble getting the list of loaded images using SwingWorker.

This is what happens in the background it just publishes the results to a TextArea

 // In a thread
@Override
public List<Image> doInBackground() {
List<Image> images = new ArrayList<Image>();
for (File filename : filenames) {
  try {
    //File file = new File(filename);
    System.out.println("Attempting to add: " + filename.getAbsolutePath());
    images.add(ImageIO.read(filename));
    publish("Loaded " + filename);
    System.out.println("Added file" + filename.getAbsolutePath());
  } catch (IOException ioe) {
    publish("Error loading " + filename);
  }
}
return images;

}
}

when it is done I just insert the images in a List<Image> and that is all it does.

// In the EDT

@Override protected void done() { try {

  for (Image image : get()) {
    list.add(image);
  }



} catch (Exception e) { }

}

Also I created an method that returns the list called getImages() what I need to get is the list from getImages() but doesn't seam to work when I call execute() for example

MySwingWorkerClass swingworker = new MySwingWorkerClass(log,list,filenames);
swingworker.execute();
imageList = swingworker.getImage()

Once it reaches the imageList it doesn't return anything the only way I was able to get the list was when i used the run() instead of the execute() is there another way to get the list or is the run() method the only way?. or perhaps i am not understanding the Swing Worker Class.

+1  A: 

I think you misundersand SwingWorker a little. Most of it is right, but you cannot call getImage() immediately after execute() - the execute call returns immediately, and your images are being loaded on the worker thread. So, the immediate call to getImages() has no images to fetch.

To fix this, you should do your image handling in the done() override, e.g. adding the images to the UI component that will display them.

mdma
+1  A: 

...or perhaps i am not understanding the SwingWorker Class.

You should be aware of the life-cycle of the SwingWorker. When you call execute, your processing will switch to a background thread and the current thread will return immediately. This is why your getImages does not return anything. From the javadoc:

Workflow

There are three threads involved in the life cycle of a SwingWorker :

Current thread: The execute() method is called on this thread. It schedules SwingWorker for the execution on a worker thread and returns immediately. One can wait for the SwingWorker to complete using the get methods.

Worker thread: The doInBackground() method is called on this thread. This is where all background activities should happen. To notify PropertyChangeListeners about bound properties changes use the firePropertyChange and getPropertyChangeSupport() methods. By default there are two bound properties available: state and progress.

Event Dispatch Thread: All Swing related activities occur on this thread. SwingWorker invokes the process and done() methods and notifies any PropertyChangeListeners on this thread.

akf
A: 

Why don't you use the publish-process mechanism to send intermediate results from the background worker thread to the EDT? Seems that you are using SwingWorker#publish(V) to tell about the progress of the task to the user and you can achieve checking the thread progress or updating a PropertyChangeListener.

Change your worker to send Images references to the EDT and override SwingWorkerprocess(List<V> chunks) method to receive that Images on EDT, and update a component's model to display the pictures.

public class SwingWorker<Void,Image> {
    @Override
    public Void doInBackground() {
        Image img;
        while(....) {
            img = downloadImage();
            publish(img);
        }    
    }

    @Override
    public void process(List<Image> images) {
        //you are on the EDT now   
    }
}

Calling SwingWorker#get() method can block the EDT, meanwhile using the publish-process mechanism you can update your UI everytime a single photo become available, while the others are still downloading from the Internet or loading from the disk.

Vicente Reig