Разделенный список в Java/Swing?

У меня есть список элементов в JList для выбора пользователем. Поскольку элементов много (скажем, городов в штатах), я хочу разделить список на разделы. Однако заголовки разделов нельзя выбирать. Итак, для моего примера с городами/штатами это может выглядеть так:

  • State 1
    • City 1
    • Город 2
    • Город 3
  • State 2
    • City 4
    • Город 5
    • Город 6

Было бы не так сложно написать это самому, встроив JList в пользовательский ListCellRenderer, но мне интересно, есть ли уже такой класс.


person Robert Kosara    schedule 17.05.2009    source источник
comment
Классы JIDE, предложенные banjollity, великолепны, но если бы кто-нибудь мог предложить чистый компонент с открытым исходным кодом, меня бы это тоже заинтересовало (я забыл сказать, что это для использования в проекте с открытым исходным кодом). Также спасибо Тому за исправление имени класса на ListCellRenderer.   -  person Robert Kosara    schedule 17.05.2009


Ответы (4)


Я вижу, что на этот вопрос уже дан ответ, но я заметил, что Роберт прокомментировал, что надеется на решение с открытым исходным кодом. Я бы рекомендовал использовать список разделителей Glazed Lists, API которого можно найти здесь:

http://publicobject.com/glazedlists/glazedlists-1.8.0/api/ca/odell/glazedlists/SeparatorList.html

Вот пример кода, который создаст список элементов, сгруппированных по их первой букве:

замещающий текст http://img300.imageshack.us/img300/8977/separatorlist.png< /а>

public class SeparatorListTest {

private static Comparator<String> createComparator() {
    return new Comparator<String>() {
        public int compare(String stringOne, String stringTwo) {
            return stringOne.substring(0,1).compareTo(stringTwo.substring(0,1));
        }
    };
}

private static ListCellRenderer createListCellRenderer() {
    return new DefaultListCellRenderer() {
        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);

            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) {
    EventList<String> rawList = GlazedLists.eventListOf(
            "apple", "appricot", "acorn", "blueberry", "coconut", "chesnut", "grape");
    SeparatorList<String> separatorList = 
            new SeparatorList<String>(rawList, createComparator(), 1, 1000);

    JList list = new JList(new EventListModel<String>(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);
}

}

person Ken    schedule 04.08.2009

В JIDE есть компонент, который позволяет делать именно это. Он называется GroupList:

альтернативный текст

person banjollity    schedule 17.05.2009
comment
Это точно! Спасибо! Я надеялся на что-то с открытым исходным кодом (забыл сказать, что это для использования в проекте с открытым исходным кодом), но похоже, что у них хорошая политика в отношении использования в проектах с открытым исходным кодом. Если кто-то может предложить версию с открытым исходным кодом, я все равно был бы признателен. - person Robert Kosara; 17.05.2009

Возможно, с помощью JTree? То, что вы описываете, представляет собой дерево с двумя уровнями.

person Valentin Rocher    schedule 17.05.2009
comment
Дерево будет чрезмерно усложнять пользовательский интерфейс. Там слишком много деревьев. - person Tom Hawtin - tackline; 17.05.2009
comment
Том прав, дерево, возможно, подойдет, но это неправильная метафора. Моя иллюстрация в вопросе была не очень хорошей, но скриншот banjolitity показывает, что я имею в виду. - person Robert Kosara; 17.05.2009

Вы можете использовать то, что Apple называет SourceList. Вы видите их в действии в iTunes и в Finder Mac OS X. Это элегантное решение проблемы, которую вы описываете.

Кроссплатформенный компонент Java Swing с открытым исходным кодом для этого находится здесь: http://explodingpixels.wordpress.com/2008/09/08/mac-widgets-for-java/

person Steve McLeod    schedule 18.05.2009
comment
Это не совсем то, что я искал здесь с моим вопросом, но я некоторое время искал такие вещи в Java. Отличный материал, спасибо! - person Robert Kosara; 18.05.2009