Изменить отображение ComboBox в Swing - PullRequest
3 голосов
/ 12 октября 2011

Я хочу изменить отображение (не редактируемого) JComboBox таким образом, чтобы текущая выбранная запись имела дополнительный текст в поле редактирования (хотя не в раскрывающемся списке) .

Примерно так:

Mockup

Моим первым предположением было переопределить модель ComboBox, чтобы getSelectedItem возвращал объект-оболочку, модифицирующий отображение:

petList.setModel(new ComboBoxModel() {
    private Object selected;

    public void setSelectedItem(Object anItem) {
        selected = anItem;
    }

    public Object getSelectedItem() {
        return new ActiveComboItem(selected);
    }

    // … The rest of the methods are straightforward.
});

Где ActiveComboItem выглядит следующим образом:

static class ActiveComboItem {
    private final Object item;

    public ActiveComboItem(Object item) { this.item = item; }

    @Override
    public boolean equals(Object other) {
        return item == null ? other == null : item.equals(other);
    }

    @Override
    public String toString() { return String.format("Animal: %s", item); }
}

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

Wrong display

(Обратите внимание на отсутствующий флажок ... или, тем не менее, выбор отображается вашей ОС.)

Дальнейшая проверка показывает, что метод getElementAt модели вызывается с индексом -1 каждый раз, когда пользователь выбирает новый элемент в поле. Это только случай, когда используется измененный выбранный элемент. Когда метод getSelectedItem модели возвращает простой объект без оболочки, выбранный элемент помечается как выбранный в раскрывающемся списке, и getElementAt - это , а не , вызываемый с аргументом -1.

Очевидно, ComboBox сравнивает каждый элемент по очереди с текущим активным элементом, но, несмотря на мое переопределение метода equals, не находит соответствия. Как я могу это исправить?

(Полный скомпилированный код для этой проблемы на gist.github.com )

Ответы [ 2 ]

7 голосов
/ 12 октября 2011

Вам необходимо предоставить пользовательский ListCellRenderer. Следующие работы:

    final JComboBox animalCombo = new JComboBox(animals);
    animalCombo.setRenderer(new DefaultListCellRenderer() {
        @Override
        public Component getListCellRendererComponent(final JList list, Object value, final int index, final boolean isSelected,
                final boolean cellHasFocus) {

            if (index == -1) {
                value = "Animal: " + value;
            }

            return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        }
    });

Индекс равен -1, если значение его рисования не соответствует раскрывающемуся.

Для дальнейшего использования, когда вы просто хотите изменить способ отображения чего-либо в Swing, вы никогда не захотите модифицировать модель поддержки. У каждого компонента есть средство рендеринга, и, как правило, вам просто нужно немного изменить стандартный.

0 голосов
/ 12 октября 2011

создать JTextField и JButton с Icon, для JButton реализует ButtonModel, переопределив его методы isRollover(), isPressed(), isArmed()

не извлекайте Icon из JComboBox, нарисуйте собственный треугольник, тогда JButton с Icon будет Look and Feel и Native OS resist, для более хороших выходных орудий JButton#setRolloverIcon() тоже

создать JPopup или JWindow, поставить здесь JScrollPane, отобразить этот контейнер из model.isPressed() или isArmed

теперь у вас есть два варианта

1) создать JList, содержащее JCheckBox (удалить прямоугольник из JCheckBox)

import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;

public class CheckList {

    public static void main(String args[]) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // Create a list containing CheckListItem's
        JList list = new JList(new CheckListItem[]{
                    new CheckListItem("apple"),
                    new CheckListItem("orange"),
                    new CheckListItem("mango"),
                    new CheckListItem("paw paw"),
                    new CheckListItem("banana")});
        // Use a CheckListRenderer (see below) to renderer list cells
        list.setCellRenderer(new CheckListRenderer());
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.addMouseListener(new MouseAdapter() {// Add a mouse listener to handle changing selection

            @Override
            public void mouseClicked(MouseEvent event) {
                JList list = (JList) event.getSource();
                int index = list.locationToIndex(event.getPoint());// Get index of item clicked
                CheckListItem item = (CheckListItem) list.getModel().getElementAt(index);
                item.setSelected(!item.isSelected()); // Toggle selected state
                list.repaint(list.getCellBounds(index, index));// Repaint cell
            }
        });
        frame.getContentPane().add(new JScrollPane(list));
        frame.pack();
        frame.setVisible(true);
    }
}

// Represents items in the list that can be selected
class CheckListItem {

    private String label;
    private boolean isSelected = false;

    public CheckListItem(String label) {
        this.label = label;
    }

    public boolean isSelected() {
        return isSelected;
    }

    public void setSelected(boolean isSelected) {
        this.isSelected = isSelected;
    }

    @Override
    public String toString() {
        return label;
    }
}

// Handles rendering cells in the list using a check box
class CheckListRenderer extends JCheckBox implements ListCellRenderer {

    private static final long serialVersionUID = 1L;

    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean hasFocus) {
        setEnabled(list.isEnabled());
        setSelected(((CheckListItem) value).isSelected());
        setFont(list.getFont());
        setBackground(list.getBackground());
        setForeground(list.getForeground());
        setText(value.toString());
        return this;
    }
}

.

2) или реализует ListSelectionModel и добавляет / удаляет Icon на MouseClick

скрыть JPopup или JWindow из MouseListener Событие

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...