This discussion is archived
4 Replies Latest reply: Mar 12, 2012 11:31 AM by Maxideon RSS

JList not showing images

Sreram Newbie
Currently Being Moderated
I have a set of images which i want to populate in a jList. So I created a customcellrenderer class which basically extends listcellrenderer to override getListCellRendererComponent to return a label with the particular image.

Now i populate the list via Swingworker, by adding elements to the model and setting it. But when i view the list in the frame (UI) i dont see any images and the list seems empty, while i have the images at the backend. I get the images to be seen once the control repaints itself after some UI operations. I tried re-validating the list, repainting the list, repainting the whole frame to display it as soon as images are loaded, in no avail. Code snippet is given below.

//Earlier in the code
list.setModel(new DefaultListModel());


Overridden method:
@Override
public Component getListCellRendererComponent(JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(list, value, index,
isSelected, cellHasFocus);
DialItem item = (DialItem) value;
Image img = null;
renderer.setVerticalAlignment(SwingConstants.BOTTOM);
renderer.setHorizontalAlignment(SwingConstants.CENTER);
img = item.getImage();
renderer.setIcon(new ImageIcon(img));
renderer.setHorizontalTextPosition(SwingConstants.CENTER);
renderer.setVerticalTextPosition(SwingConstants.BOTTOM);
renderer.setToolTipText(item.getImageName());
return renderer;
}

Swingworker code:

SwingWorker<Void, Void> readImage = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
for (int iter = 0; iter < fileList; iter++) {// file : fileList
DefaultListModel model = (DefaultListModel) list.getModel();
DialItem item = new DialItem();
item.setImageName(fileList.get(iter).getName());
item.setImage(getImagefromFile(fileList.get(iter)));
model.addElement(item);
list.setModel(model);
}
return null;

}
};
readImage.execute();


And i have this problem only when i load it via swing-worker and not otherwise. Does somebody have any clue what is exactly happening..?
  • 1. Re: JList not showing images
    Maxideon Explorer
    Currently Being Moderated
    Try this as the code for your SwingWorker
    SwingWorker<Void,DialItem> readImage = new SwingWorker<Void,DialItem>(){
        @Override
        protected Void doInBackground() throws Exception {
            for (File f : fileList) {
                DialItem item = new DialItem();
                item.setImageName(f.getName());
                item.setImage(getImagefromFile(f));
                publish(item);
            }
            return null;
        }
        @Override
        protected void process(List<DialItem> chunks) {
            DefaultListModel model = (DefaultListModel) list.getModel();
            for(DialItem item : chunks) {
                model.addElement(item);
            }
            list.repaint();
        }
    };
    readImage.execute();
    You should try to only change a model on the EDT. In theory the model will signify the change to the UI and a repaint is called, but adding your own repaint shouldn't hurt anything.
  • 2. Re: JList not showing images
    801313 Explorer
    Currently Being Moderated
    You might want to consider using MediaTracker to track your image downloads. It's probably a timing thing
  • 3. Re: JList not showing images
    Sreram Newbie
    Currently Being Moderated
    Thanks for your reply.

    But I have two questions here. One, do you say because i set the model each time, sometimes the list is not getting repainted? If that is the case, it must not work, especially for large images... But in my case its just the opposite. For large images(~MB size) its working fine, but the problem is only for small images (~few kb)

    And two, I have already tried giving list.revalidate(), list.repaint() in the loop, when the worker has done its job, by overriding the done method... in vain... Will the splitting up of worker as process chunks be of any use?

    Any ways, will try and get back to you. Thank you once again for the reply.
  • 4. Re: JList not showing images
    Maxideon Explorer
    Currently Being Moderated
    One, do you say because i set the model each time, sometimes the list is not getting repainted?
    I didn't say that. It's just good concurrency practice to only manipulate models on the EDT, particularly when SwingWorker easily allows the break up of loading the images in a background thread and updating the model on the EDT through the publish/process methods.
    Will the splitting up of worker as process chunks be of any use?
    Again it's just a good habit to get into for concurrency reasons.

    As for your repainting issue, try changing this line
     
    item.setImage(getImagefromFile(f)); 
    to
     
    item.setImage(new ImageIcon(getImageFromFile(f)).getImage()); 
    The ImageIcon class uses MediaTracker to synchronously load images (you can use your own if you want). If you're getting your images via the Toolkit.createImage# methods, then the images need to be loaded. Usually what happens is the toolkit image will get loaded when first drawn. The component that's doing the drawing gets repainted as more of the image comes in. But in the case of a JList, that component is the cell renderer pane and it doesn't care about repaint() calls. So changing the above line will insure the images are already loaded and ready to draw when first shown. tjacobs01 post reminded me of this.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points