问题
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