How to change appearance of JComboBox's display area

喜你入骨 提交于 2021-02-08 04:47:40

问题


I'm using a custom BasicComboBoxRenderer for a JComboBox and I've changed the appearance of the items of the drop-down list. However these changes also apply to the single top item that shows in the combobox (don't know how to call it).

I want the top item to be independent of the other items in the list, if possible. I would also like to get rid of the top item's blue color when it is focused (setFocusable(false) is not what I want).

I've tried to use the "renderer index" (-1) to affect the top item but it doesn't seem to help.

Any ideas?

P.S Unfortunately I couldn't add images to be more clear (no reputation).

EDIT: When I say that I want the top item to be independent from all the other items of the drop-down list I mean to always look different from the rest of them. For example in my custom BasicComboBoxRenderer I've set the selected item to have a different background, but this background also applies to the top item (since the selected item becomes the top item of the combobox).

EDIT 2: top item = I meant the combobox display area, so I want to affect the item that is shown at the display area and not the first item in the drop-down list. I managed to do this by using setBackground on the combobox itself AND setFocusable(false) (which is not very helpful because I want to keep the focus mechanism). But the problem is (except the focus issue) that if for example I set a border on each item in the list through a custom BasicComboBoxRenderer or ListCellRenderer class, this same border appears on the item that is shown in the display area. So there are 2 questions here:

--Is there any way to differentiate the layout of the items in the drop-down list and the single item in the display area?

--Is there any way to disable the focus color of the combobox without disabling the focus mechanism, just like when we use setFocusPainted(false) on buttons? (I've also tried to add a custom FocusListener on the combobox but any change made of the background through focusGained() affects only the button and not the item shown in the display area).

Sorry for the confusion and the multiple edits...


回答1:


  • have look at Combo Box Prompt by @camickr,

  • defined prompt can't returns any value from JComboBox.getSelectedXxx

EDIT

BasicComboBoxRenderer or ListCellRenderer can do that this way

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;
        }
    }
}

EDIT2

JComboBox has two states

  • editable

  • non_editable

basically all values could be accesible from UIManager, shortcuts

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();
            }
        });
    }
}


来源:https://stackoverflow.com/questions/11420217/how-to-change-appearance-of-jcomboboxs-display-area

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!