0

I'm new to Java swing and I'm trying to create a list view showing content of a directory. I expect to create a view like following image: enter image description here

I know how to use JList, but I don't know how to show icons matching with types of files. As you can see, from the image, we can visually differentiate pdf files with text files and others. Should I try to use JList or another UI component?

lenhhoxung
  • 2,530
  • 2
  • 30
  • 61

1 Answers1

4

I have done something similar; here's an example of my output.

enter image description here

I used a custom renderer for the tree; it produces the indentation, icon, and text that you see in one cell of the leftmost column of the display. Here's the source for that:

package spacecheck.ui.renderer;

import java.awt.Component;

import javax.swing.ImageIcon;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;

import spacecheck.filedata.FileCollection;
import spacecheck.images.TreeIcon;

/**
 * renders the name of a collection for the tree display.
 * @author rcook
 *
 */
public class CollectionNameRenderer extends DefaultTableCellRenderer // which implements JLabel
//    implements TableCellRenderer
{
  private static final long serialVersionUID = 1L;
  @SuppressWarnings({"unused"})
  private void say(String msg) { System.out.println(msg); }

  private static TreeIcon tIcon = null;

  /**
   * set the value of the CollectionName for the JTable; includes using
   * indent so that the correct icon can be obtained (icons are different widths
   * to implement different indent levels).
   */
  public void setValue(Object value)
  {
    FileCollection fc = (FileCollection)value;
    boolean expanded = fc.isExpanded();
    int level = fc.getDisplayLevel();
//    boolean isSelected = table.
    ImageIcon icon = tIcon.getIcon(level, expanded);
    if (icon != null) { setIcon(icon); }
    setText(value.toString());
  }

  /**
   * get the renderer component for a collection name.
   */
  public Component getTableCellRendererComponent
      (JTable table, Object value, boolean isSelected, boolean hasFocus, 
          int rowIndex, int colIndex)
  {
    if (tIcon == null) { tIcon = new TreeIcon(table.getBackground()); }
    return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, rowIndex, colIndex);
  }
}

That class uses another of mine named TreeIcon; it implements the indentation of the folder icon as shown in the picture as well as choosing the icon depending on the expanded/unexpanded state of the folder. Here's that class:

package spacecheck.images;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 * represents an icon used in the directory tree; handles 'expanded' and
 * 'unexpanded' directories as well as indentation representing different
 * levels.
 * @author rcook
 *
 */
public class TreeIcon
{
  public static int UNEXPANDED = 1;
  public static int EXPANDED = 2;

  @SuppressWarnings({"unused"})
  private void say (String msg) { System.out.println(msg); }

  private static ImageIcon expandedIcon = null;
  private static ImageIcon unexpandedIcon = null;
  private static int       iconHeight = 0;
  private static int       iconWidth  = 0;

  private static ArrayList<ImageIcon> cachedExpandedIcons = new ArrayList<ImageIcon>();
  private static ArrayList<ImageIcon> cachedUnexpandedIcons = new ArrayList<ImageIcon>();

  static
  {
    expandedIcon = new ImageIcon(TreeIcon.class.getResource("images/Expanded.png"));
    unexpandedIcon = new ImageIcon(TreeIcon.class.getResource("images/Unexpanded.png"));
    iconHeight = unexpandedIcon.getIconHeight();
    iconWidth =  unexpandedIcon.getIconWidth();
  }

  public TreeIcon(Color givenColor)  {  }

  public static void main(String ... arguments)
  {
    JFrame frame = new JFrame("icon test");
    JLabel label = new JLabel("background test");
    label.setBackground(Color.blue);
    TreeIcon treeIcon = new TreeIcon(Color.black);
    ImageIcon icon = treeIcon.getIcon(2, false);
    label.setIcon(icon);
    frame.add(label);
    frame.pack();
    frame.setVisible(true);
  }

  /**
   * return the icon for an expanded or unexpanded level
   * @param int level of folder relative to other levels displayed;
   * starts at 0 and increases with depth
   * @param boolean indicates whether this level is expanded or not.
   * @return ImageIcon appropriate for expansion flag and level.
   */
  public ImageIcon getIcon(int level, boolean expanded)
  {
    ImageIcon result = null;

    if (level < 0)
    { System.out.println("level is " + level + ", setting to 0");
      level = 0;
    }

    // set our list of icons depending on whether we are expanded.
    ArrayList<ImageIcon> cachedIcons = cachedUnexpandedIcons;
    if (expanded) { cachedIcons = cachedExpandedIcons; }

    // if we already have this icon in our cache, return it.
    if (cachedIcons.size() >= (level+1) && cachedIcons.get(level) != null)
    {
      result = cachedIcons.get(level);
    }
    else
    {
      // generate this icon and store it in the cache before returning it.
      ImageIcon baseIcon = unexpandedIcon;
      if (expanded) { baseIcon = expandedIcon; }
      int iconH = iconHeight;
      int iconW = iconWidth*(level+1);

      BufferedImage bufferedImage = new BufferedImage(iconW,iconH,BufferedImage.TYPE_INT_ARGB);
      Graphics g = bufferedImage.getGraphics();

      g.drawImage(baseIcon.getImage(), iconWidth*level, 0, null);

      result = new ImageIcon(bufferedImage);

      // we've created an icon that was not in the cached list; 
      // the cached list may have a null at this slot, or it may not yet be
      // long enough to have this slot.  Ensure that we have enough slots
      // in the list, and then add this icon.
      for (int i=cachedIcons.size(); i<=level; i++)
      {
        cachedIcons.add(null);
      }
//      if (cachedIcons.size() < level + 1) { cachedIcons.add(result); }
//                                     else { 
      cachedIcons.set(level, result); 
//      }
//      say("adding icon, level = " + level + (expanded ? " " : " un") + "expanded, width = " + iconW);
    }

    return result;
  }
}

To choose icons for different kinds of files, you could have your renderer and icon-chooser look at the file extension (or whatever) to determine which icon out of a map to use.

Hope that helps!

arcy
  • 12,845
  • 12
  • 58
  • 103