4 Replies Latest reply: Mar 12, 2012 11:31 AM by Maxideon RSS

    JList not showing images

    Sreram
      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
          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
            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
              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
                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.