Можно ли добавить дерево внутри JCombobox? - PullRequest
1 голос
/ 26 февраля 2020

Поскольку у меня слишком много опций в моем JComboBox, я подумал, что, может быть, было бы целесообразно перегруппировать их в зависимости от их типа в разных узлах и позволить пользователю расширять или сворачивать их в зависимости от того, какой тип им нравится. Это улучшило бы удобочитаемость JComboBox и сэкономило бы пользователю много времени на прокрутку вниз или вверх в поисках его варианта.

Вопрос теперь в том, возможно ли добавить дерево в JComboBox?

Наиболее близким к решению, которое я нашел на SO, является следующее: Одна альтернатива

Человек, предложивший альтернативу, предлагает следующее:

Если вам нужно расширение узлов, то лучшим вариантом будет добавить всплывающее окно, которое появляется под кнопкой, которая прослушивает выбор элементов в дереве. Нечто подобное может быть лучшим выбором в зависимости от того, как выстроен ваш GUI.

Но, и, если я не понял, что они говорят, они не добавляют дерево внутри JComboBox, который это действительно то, что я хочу здесь.

1 Ответ

2 голосов
/ 26 февраля 2020

Да, вы можете заменить JList во всплывающем компоненте на JTree. Но вам также необходимо обеспечить связь между ComboBoxModel и TreeModel (когда элемент выбран в JTree, он также будет выбран в JComboBox и наоборот). Например, вы можете построить реализацию ComboBoxModel, которая имеет TreeModel в качестве делегата и обеспечивает линеаризацию вашего дерева каждый раз, когда ваш TreeModel изменяется (запускает TreeModelEvent), чтобы получить список элементов для выпадающего списка. Также вам нужно обеспечить реакцию на события мыши / клавиши в вашем дереве, чтобы обновить выделение в вашем комбинированном списке.

Вот метод, который вы можете использовать, чтобы установить любой компонент как всплывающее окно JComboBox (в вашем случае это должен быть JScrollPane, который обернет вашу JTree):

/**
 * Sets the custom component as popup component for the combo-box.
 *
 * @param combo combo-box to get new popup component.
 * @param comp new popup component.
 * @param widthIncr width increment for pop-up.
 * @param heightIncr height increment for pop-up.
 */
public static void setPopupComponent(JComboBox<?> combo, Component comp, int widthIncr, int heightIncr) {
    final ComboPopup popup = (ComboPopup) combo.getUI().getAccessibleChild(combo, 0);
    if (popup instanceof Container) {
        final Container c = (Container) popup;
        c.removeAll();
        c.setLayout(new GridLayout(1, 1));
        c.add(comp);
        final Dimension size = comp.getPreferredSize();
        size.width += widthIncr;
        size.height += heightIncr;
        c.setPreferredSize(size);
    }
}

Параметры widthIncr и heightIncr могут быть использованы для некоторых Look-and-Feels, чтобы лучше принять ширину / высоту по умолчанию всплывающее окно в вашем выпадающем списке.

...