Creating a separated JList using Glazed Lists

August 5, 2009

SeparatorList
I’ve been espousing the power of Glazed Lists for a long time, and won’t be stopping any time soon! I recently needed a JList that visually grouped items into categories. GL made this super simple.

Here’s how you can create a SeparatorList, which will auto-magically insert separators into your JList for you. We’ll create a simple list of items that we want grouped by their first letter.

public class SeparatorListTest {

    /**
     * Creates a {@link Comparator} that compares the first letter of two given strings.
     */
    private static Comparator createComparator() {
        return new Comparator() {
            public int compare(String stringOne, String stringTwo) {
                return stringOne.substring(0,1).compareTo(stringTwo.substring(0,1));
            }
        };
    }

    /**
     * Creates a renderer that can render both separators and regular items.
     */
    private static ListCellRenderer createListCellRenderer() {
        return new DefaultListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(
                    JList list, Object value, int index, boolean isSelected, 
                    boolean cellHasFocus) {
                
                // call the super renderer to take care of setting the foreground and
                // background colors.
                JLabel label = (JLabel) super.getListCellRendererComponent(
                        list, value, index, isSelected, cellHasFocus);

                // if the item being renderered is a separator, then bold it, and shift
                //    in slightly.
                // else if the item being rendered is an actual list item, make it plain
                //    and shift it in more.
                if (value instanceof SeparatorList.Separator) {
                    SeparatorList.Separator separator = (SeparatorList.Separator) value;
                    label.setText(separator.getGroup().get(0).toString().substring(0,1));
                    label.setFont(label.getFont().deriveFont(Font.BOLD));
                    label.setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
                } else {
                    label.setFont(label.getFont().deriveFont(Font.PLAIN));
                    label.setBorder(BorderFactory.createEmptyBorder(0,15,0,0));
                }

                return label;
            }
        };
    }

    public static void main(String[] args) {
        // create a list of items.
        EventList rawList = GlazedLists.eventListOf(
                "apple", "appricot", "acorn", "blueberry", "coconut", "chesnut", "grape");
        // create a SeparatorList based on the raw list of items using the "first-letter"
        // comparator to group them.
        SeparatorList separatorList =
                new SeparatorList(rawList, createComparator(), 0, 1000);

        JList list = new JList(new EventListModel(separatorList));
        list.setCellRenderer(createListCellRenderer());
        JScrollPane scrollPane = new JScrollPane(list);
        scrollPane.setBorder(null);

        JFrame frame = new JFrame();
        frame.add(scrollPane, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(200,200);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

6 Responses to “Creating a separated JList using Glazed Lists”

  1. Eric Burke Says:

    Good tip, but I’d cache those Borders, otherwise every repaint creates new instances.

    • Ken Says:

      Sure… that would be an optimization. Some would say that short lived objects are better though, depending on the situation.


  2. I am impressed, I used JXList for some projects, but this one seems “a lot” simpler.


  3. […] Orr keeps the Swing section alive this week, with a post on how to create a separated JList using GlazedLists. Having used GlazedLists myself in projects, I can vouch for it’s awesomeness. If […]


  4. PLEASE NO MATTER WHAT, DO NOT CLOSE THIS WEBSITE hahaha this one is a gem, it helped me a lot to use these mac widgets for my project.. more powers!


Leave a comment