Creating a separated JList using Glazed Lists
August 5, 2009
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); } }
August 5, 2009 at 7:49 pm
Good tip, but I’d cache those Borders, otherwise every repaint creates new instances.
August 5, 2009 at 9:15 pm
Sure… that would be an optimization. Some would say that short lived objects are better though, depending on the situation.
August 8, 2009 at 8:30 pm
I am impressed, I used JXList for some projects, but this one seems “a lot” simpler.
August 8, 2009 at 10:21 pm
Yeah… I find Glazed Lists extremely straight forward and easy to use.
August 9, 2009 at 9:39 pm
[…] 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 […]
May 4, 2012 at 4:01 am
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!