Как изменить внешний вид области отображения JComboBox

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

Я хочу, чтобы верхний элемент не зависел от других элементов в списке, если это возможно. Я также хотел бы избавиться от синего цвета верхнего элемента, когда он сфокусирован (setFocusable(false) - это не то, что мне нужно).

Я пытался использовать «индекс рендерера» (-1), чтобы воздействовать на верхний элемент, но, похоже, это не помогает.

Любые идеи?

P.S. К сожалению, я не смог добавить изображения, чтобы было понятнее (нет репутации).

РЕДАКТИРОВАТЬ: Когда я говорю, что хочу, чтобы верхний элемент был независим от всех остальных элементов раскрывающегося списка, я имею в виду, что он всегда будет отличаться от остальных. Например, в моем пользовательском BasicComboBoxRenderer я установил для выбранного элемента другой фон, но этот фон также применяется к верхнему элементу (поскольку выбранный элемент становится верхним элементом списка).

РЕДАКТИРОВАТЬ 2: верхний элемент = Я имел в виду область отображения поля со списком, поэтому я хочу повлиять на элемент, отображаемый в области отображения, а не на первый элемент в раскрывающемся списке. Мне удалось сделать это, используя setBackground в самом поле со списком И setFocusable(false) (что не очень полезно, потому что я хочу сохранить механизм фокуса). Но проблема (за исключением проблемы с фокусом) заключается в том, что если, например, я устанавливаю границу для каждого элемента в списке с помощью пользовательского класса BasicComboBoxRenderer или ListCellRenderer, эта же граница появляется для элемента, отображаемого в области отображения. Так вот тут 2 вопроса:

-- Есть ли способ различать расположение элементов в раскрывающемся списке и один элемент в области отображения?

-- Есть ли способ отключить цвет фокуса поля со списком, не отключая механизм фокуса, как когда мы используем setFocusPainted(false) для кнопок? (Я также пытался добавить собственный FocusListener в поле со списком, но любое изменение фона с помощью focusGained() влияет только на кнопку, а не на элемент, отображаемый в области отображения).

Извините за сумбур и многократные правки...


person Rempelos    schedule 10.07.2012    source источник


Ответы (1)


  • взгляните на Combo Box Prompt от @camickr,

  • определенная подсказка не может вернуть какое-либо значение из JComboBox.getSelectedXxx

РЕДАКТИРОВАТЬ

BasicComboBoxRenderer или ListCellRenderer могут сделать это таким образом.

import java.awt.*;
import javax.swing.*;

public class TestHighLightRow {

    public void makeUI() {
        Object[] data = {"One", "Two", "Three"};
        JComboBox comboBox = new JComboBox(data);
        comboBox.setPreferredSize(comboBox.getPreferredSize());
        comboBox.setRenderer(new HighLightRowRenderer(comboBox.getRenderer()));
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(comboBox);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestHighLightRow().makeUI();
            }
        });
    }

    public class HighLightRowRenderer implements ListCellRenderer {

        private final ListCellRenderer delegate;
        private int height = -1;

        public HighLightRowRenderer(ListCellRenderer delegate) {
            this.delegate = delegate;
        }

        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            Component component = delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            Dimension size = component.getPreferredSize();
            if (index == 0) {
                component.setBackground(Color.red);
                if (component instanceof JLabel) {
                    ((JLabel) component).setHorizontalTextPosition(JLabel.CENTER);
                }
            }
            return component;
        }
    }
}

РЕДАКТИРОВАТЬ2

JComboBox имеет два состояния

  • редактируемый

  • non_editable

в основном все значения могут быть доступны из UIManager, ярлыков

import java.awt.*;
import java.util.Vector;
import javax.swing.*;
import javax.swing.UIManager;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.metal.MetalComboBoxButton;

public class MyComboBox {

    private Vector<String> listSomeString = new Vector<String>();
    private JComboBox someComboBox = new JComboBox(listSomeString);
    private JComboBox editableComboBox = new JComboBox(listSomeString);
    private JComboBox non_EditableComboBox = new JComboBox(listSomeString);
    private JFrame frame;

    public MyComboBox() {
        listSomeString.add("-");
        listSomeString.add("Snowboarding");
        listSomeString.add("Rowing");
        listSomeString.add("Knitting");
        listSomeString.add("Speed reading");
//
        someComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
        someComboBox.setFont(new Font("Serif", Font.BOLD, 16));
        someComboBox.setEditable(true);
        someComboBox.getEditor().getEditorComponent().setBackground(Color.YELLOW);
        ((JTextField) someComboBox.getEditor().getEditorComponent()).setBackground(Color.YELLOW);
//
        editableComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
        editableComboBox.setFont(new Font("Serif", Font.BOLD, 16));
        editableComboBox.setEditable(true);
        JTextField text = ((JTextField) editableComboBox.getEditor().getEditorComponent());
        text.setBackground(Color.YELLOW);
        JComboBox coloredArrowsCombo = editableComboBox;
        Component[] comp = coloredArrowsCombo.getComponents();
        for (int i = 0; i < comp.length; i++) {
            if (comp[i] instanceof MetalComboBoxButton) {
                MetalComboBoxButton coloredArrowsButton = (MetalComboBoxButton) comp[i];
                coloredArrowsButton.setBackground(null);
                break;
            }
        }
//
        non_EditableComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
        non_EditableComboBox.setFont(new Font("Serif", Font.BOLD, 16));
//
        frame = new JFrame();
        frame.setLayout(new GridLayout(0, 1, 10, 10));
        frame.add(someComboBox);
        frame.add(editableComboBox);
        frame.add(non_EditableComboBox);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocation(100, 100);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        UIManager.put("ComboBox.background", new ColorUIResource(Color.yellow));
        UIManager.put("JTextField.background", new ColorUIResource(Color.yellow));
        UIManager.put("ComboBox.selectionBackground", new ColorUIResource(Color.magenta));
        UIManager.put("ComboBox.selectionForeground", new ColorUIResource(Color.blue));
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                MyComboBox aCTF = new MyComboBox();
            }
        });
    }
}
person mKorbel    schedule 10.07.2012
comment
Спасибо за интересную ссылку.. Однако это не то, что я ищу.. Я хочу, чтобы верхний элемент (независимо от того, какое значение он показывает) отличался от всех других элементов раскрывающегося списка (например, всегда иметь другой фон). - person Rempelos; 11.07.2012
comment
хорошо, еще раз спасибо за ваше время... Я не ясно выразился, потому что я не знаю правильной терминологии для этого. Я снова отредактировал свой вопрос. - person Rempelos; 11.07.2012
comment
Эй, ты быстрый... Твое третье поле со списком было тем, что я хотел. Я вижу, что с помощью UIManager проблема с фокусом также решена... Спасибо! - person Rempelos; 11.07.2012
comment
На самом деле это не повлияло на выбранный элемент в поле со списком. Мне пришлось вручную применить стиль к самому полю со списком, используя ItemListener для отслеживания событий выбора. - person 2rs2ts; 09.05.2014
comment
@ 2rs2ts понятия не имею, о чем ты говоришь, тебе нужно предоставить больше информации, чем это - person mKorbel; 10.05.2014
comment
@mKorbel Я хочу сказать, что этот метод работал для элементов раскрывающегося списка, но что касается фактического поля, показывающего выбранный элемент, этот метод ничего не делал. Мне пришлось использовать прослушиватель, который применял бы стиль к полю со списком (а не к ячейкам списка), чтобы выбранное значение имело тот же стиль. ОП описывал аналогичную проблему, но теперь я вижу, что он хотел поведения, которое я описываю. Я подумал, что, возможно, мой комментарий будет достойным предупреждением для тех, кто это читает. - person 2rs2ts; 12.05.2014
comment
@ 2rs2ts вопрос о редакторе (выбор из drop_down_list), ничего о событиях за пределами JComboBox, тогда ItemLisener является правильным способом, но никто не знает, есть разница между событиями в API от ItemListener и ActionListener - person mKorbel; 12.05.2014
comment
Связано с EDIT1: это лучшая реализация, которую я когда-либо видел, которая позволяет использовать Windows и Mac Look and Feel без дефектов графического интерфейса. +1 - person dARKpRINCE; 02.06.2014