Search code examples
javaswingjlabelembedded-resource

How to get my JLabel Icons to render in my JList?


So I have a JList of JLabel objects that have an Image and some Text attached to them.

Results

Everything looking good except for the fact that the icons are not displaying the images.

public static void createIcons(){
    char[] extension = new char[4];
    Image img;
    try {
        for(int i = 0; i < FtpClient.FilesOnServer.length; i++) {
            for(int j = 0; j < 4; j++) {
                extension[3 - j] = FtpClient.FilesOnServer[i].charAt(FtpClient.FilesOnServer[i].length() - (j+1));
                if(j == 3) {
                    System.out.println(extension);
                    String fileType = new String(extension);
                    JLabel iconLabel = new JLabel();
                    switch (fileType){
                    case ".pdf":
                        iconLabel.setIcon(new ImageIcon(FtpWindow.class.getResource("icons\\text.png")));
                        break;
                    case ".png":
                        iconLabel.setIcon(new ImageIcon(FtpWindow.class.getResource("icons\\picture.png")));
                        break;
                    case ".jpg":
                        iconLabel.setIcon(new ImageIcon(FtpWindow.class.getResource("icons\\picture.png")));
                        break;
                    case ".txt":
                        iconLabel.setIcon(new ImageIcon(FtpWindow.class.getResource("icons\\text.png")));
                        break;
                    default:
                        iconLabel.setIcon(new ImageIcon(FtpWindow.class.getResource("icons\\default.png")));
                        break;
                    }
                    iconLabel.setText(FtpClient.FilesOnServer[i]);
                    iconLabel.setVerticalTextPosition(SwingConstants.BOTTOM);
                    iconLabel.setVerticalAlignment(SwingConstants.BOTTOM);
                    model.addElement(iconLabel);
                }
            }
        }
        T_FileLayout = new JList(model);
    } catch(Exception ex){
        ex.printStackTrace();
    }
}

public static void BuildFtpWindow(){
    P_FilesOnServer = new JPanel();
    B_UPLOAD.setBounds(10, 9, 110, 25);
    B_UPLOAD.setText("UPLOAD");
    B_DOWNLOAD.setBounds(10, 39, 110, 25);
    B_DOWNLOAD.setText("DOWNLOAD");
    P_FilesOnServer.setBounds(130, 9, 320, 288);
    P_FilesOnServer.setBackground(new Color(255, 255, 255));
    createIcons();
    P_FilesOnServer.add(T_FileLayout);
    ServerBrowser.add(P_FilesOnServer);
    ServerBrowser.add(B_DOWNLOAD);
    ServerBrowser.add(B_UPLOAD);
}

I have seen a post about overriding DefaultListCellRenderer, but I have no idea what I am supposed give it for Object Value. I am just trying to display the Icon and the Text that go with it. I feel like I am close, but just cannot figure out why its not behaving.

Getting similar behavior like before, it appears to be giving a reference to the object instead of rendering them.New Result

Here is the class I created (it is in its own class file and not butted up against the code after it). And the calls along with the overridden function.

import java.awt.Image;
import javax.swing.ImageIcon;

public class ServerFileIcon{

  public ImageIcon Image;
  public String Text;

  public void setImage(String path){
      Image = new ImageIcon(getClass().getResource(path));
  }

  public void setText(String text){
      Text = text;
  }

  public ImageIcon getIcon(){
      return Image;
  }

  public String getText(){
      return Text;
  }
}

ServerFileIcon iconLabel = new ServerFileIcon();
              switch (fileType){
                  case ".pdf":
                    iconLabel.setImage("icons\\text.png");
                    break;
                  case ".png":
                    iconLabel.setImage("icons\\picture.png");
                    break;
                  case ".jpg":
                    iconLabel.setImage("icons\\picture.png");
                    break;
                  case ".txt":
                    iconLabel.setImage("icons\\text.png");
                    break;
                  default:
                    iconLabel.setImage("icons\\default.png");
                    break;
              }
              iconLabel.setText(FtpClient.FilesOnServer[i]);
              model.addElement(iconLabel);
            }
          }
      }
      T_FileLayout = new JList(model);
    }catch(Exception ex){
        ex.printStackTrace();
    }
  } 

   @Override
    public Component getListCellRendererComponent(JList list, Object value, int index,boolean isSelected, boolean cellHasFocus) 
    {
       super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

        ServerFileIcon customObject = (ServerFileIcon)value;

        setText( customObject.getText() );
        setIcon( customObject.getIcon() );

        return this;
    } 

Solution

  • So I have a JList of JLabel objects

    You should not be using JLabel objects in your JList. Swing components use renderers to be more efficient.

    Instead you should create a custom Object that has 2 properties: text, icon. Then in the rendering code you just set the text and the icon of the renderer (which by default is a JLabel) with the values from your custom object.

    I have seen a post about overriding DefaultListCellRenderer, but I have no idea what I am supposed give it for Object Value.

    The Object value will be the custom object mentioned above.

    So the basic code would be something like:

    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
    {
        super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
    
        MyCustomObject customObject = (MyCustomObject)value;
    
        setText( customObject.getText() );
        setIcon( customObject.getIcon() );
    
        return this;
    }