[英]JComboBox setBackground() without changing the color of the arrow
我一直試圖解決這個問題6個小時了。 我終於根據需要改變了顏色,但我只想保留組合框箭頭的默認顏色。
這是代碼......
注意:編輯后的代碼無需在圖片中顯示背景...
import org.apache.commons.lang3.ArrayUtils;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.metal.MetalComboBoxButton;
public class TestGui extends JFrame {
private final String[] guiCharSelDefault = {"--- Select Character ---"};
private final String[] characters = {"SelectedTextOne", "SelectedTextTwo", "SelectedTextThree", "SelectedTextFour"};
private final String[] guiCharSel = (String[]) ArrayUtils.addAll(guiCharSelDefault, characters);
private JComboBox charCombo = createStandardCombo(guiCharSel);
private JPanel topFrame = createTopFrame();
private JScrollPane topFrameScroll = createTopScrollPane();
private JPanel centerFrame = createCenterFrame();
//**************************************************************************************
// Constructor
TestGui(){
add(topFrameScroll, BorderLayout.NORTH);
add(centerFrame, BorderLayout.CENTER);
setSize(800,600);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
//**************************************************************************************
// Support Methods
private static GridBagConstraints setGbc(int gridx, int gridy, int gridWidth, int gridHeight, int ipadx, int ipady, String anchorLocation, double weightx, double weighty, Insets insets){
GridBagConstraints gbc = new GridBagConstraints();
if (anchorLocation.toUpperCase().equals("NORTHWEST")){
gbc.anchor = GridBagConstraints.NORTHWEST;
} else if (anchorLocation.toUpperCase().equals("NORTH")){
gbc.anchor = GridBagConstraints.NORTH;
} else if (anchorLocation.toUpperCase().equals("NORTHEAST")){
gbc.anchor = GridBagConstraints.NORTHEAST;
} else if (anchorLocation.toUpperCase().equals("WEST")){
gbc.anchor = GridBagConstraints.WEST;
} else if (anchorLocation.toUpperCase().equals("EAST")){
gbc.anchor = GridBagConstraints.EAST;
} else if (anchorLocation.toUpperCase().equals("SOUTHWEST")){
gbc.anchor = GridBagConstraints.SOUTHWEST;
} else if (anchorLocation.toUpperCase().equals("SOUTH")){
gbc.anchor = GridBagConstraints.SOUTH;
} else if (anchorLocation.toUpperCase().equals("SOUTHEAST")){
gbc.anchor = GridBagConstraints.SOUTHEAST;
} else {
gbc.anchor = GridBagConstraints.CENTER;
}
gbc.gridx = gridx; // column
gbc.gridy = gridy; // row
gbc.gridwidth = gridWidth; // number of columns
gbc.gridheight = gridHeight; // number of rows
gbc.ipadx = ipadx; // width of object
gbc.ipady = ipady; // height of object
gbc.weightx = weightx; // shifts rows to side of set anchor
gbc.weighty = weighty; // shifts columns to side of set anchor
gbc.insets = insets; // placement inside cell
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.fill = GridBagConstraints.VERTICAL;
return gbc;
}
private Insets setInsets(int top, int left, int bottom, int right){
Insets insets = new Insets(top,left,bottom,right);
return insets;
}
//**************************************************************************************
// Interactive Object Methods
private JComboBox createStandardCombo(String[] defaultValues){
JComboBox comboBox = new JComboBox(defaultValues);
ComboBoxRenderer cbr = new ComboBoxRenderer();
DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
dlcr.setHorizontalTextPosition(SwingConstants.CENTER);
comboBox.setRenderer(cbr);
comboBox.setPrototypeDisplayValue("X" + guiCharSelDefault + "X");
return comboBox;
}
//**************************************************************************************
// Object Action Methods
private void setComboBoxColorBackgroundWithMetalArrow(Color color){
int componentCount = charCombo.getComponentCount();
for (int i = 0; i < componentCount; i++) {
Component component = charCombo.getComponent(i);
if (component instanceof MetalComboBoxButton) {
MetalComboBoxButton metalComboBoxButton =
(MetalComboBoxButton) component;
Icon comboIcon = metalComboBoxButton.getComboIcon();
BufferedImage bufferedImage =
new BufferedImage(
comboIcon.getIconWidth(),
comboIcon.getIconHeight(),
BufferedImage.TYPE_INT_ARGB);
comboIcon.paintIcon(
metalComboBoxButton, bufferedImage.getGraphics(), 0, 0);
}
}
}
private void setCharComboAction(){
charCombo.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
String charName = ((JComboBox)(e.getSource())).getSelectedItem().toString();
if (!(charName.equals(guiCharSelDefault[0]))){
DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
DefaultComboBoxModel model = new DefaultComboBoxModel(characters);
model.setSelectedItem(charName);
charCombo.setModel(model);
if (charName.equals("SelectedTextOne")){
//charCombo.getEditor().getEditorComponent().setBackground(Color.GREEN);
charCombo.setBackground(Color.GREEN);
} else if (charName.equals("SelectedTextTwo")){
charCombo.setBackground(Color.RED);
} else {
charCombo.setBackground(dlcr.getBackground());
}
}
}
}
);
}
//**************************************************************************************
// Panel Methods
private JPanel createTopFrame(){
JPanel pnl = new JPanel();
pnl.setLayout(new GridBagLayout());
setCharComboAction();
pnl.add(charCombo, setGbc(0,0, 1,1, 0,0, "WEST", 0, 0, setInsets(0, 10, 0, 0)));
JButton button = new JButton("Button");
pnl.add(button, setGbc(0,1, 1,1, 0,0, "WEST", 0, 0, setInsets(0, 10, 0, 0)));
pnl.setOpaque(false);
return pnl;
}
private JScrollPane createTopScrollPane(){
JScrollPane scrollPane = new JScrollPane();
Border raisedBevel = BorderFactory.createRaisedBevelBorder();
Border lineBorder = BorderFactory.createMatteBorder(2, 2, 2, 2, new Color(224,224,224));
Border loweredBevel = BorderFactory.createLoweredBevelBorder();
Border compoundSetup = BorderFactory.createCompoundBorder(raisedBevel, lineBorder);
Border compoundFinal = BorderFactory.createCompoundBorder(compoundSetup, loweredBevel);
scrollPane.setBorder(compoundFinal);
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
scrollPane.getViewport().setView(topFrame);
return scrollPane;
}
private JPanel createCenterFrame() {
JPanel pnl = new JPanel();
Border raisedBevel = BorderFactory.createRaisedBevelBorder();
Color lineColor = new Color(224, 224, 224);
Border lineBorder = BorderFactory.createMatteBorder(5, 5, 5, 5, lineColor);
Border loweredBevel = BorderFactory.createLoweredBevelBorder();
Border compoundSetup = BorderFactory.createCompoundBorder(raisedBevel, lineBorder);
Border compoundFinal = BorderFactory.createCompoundBorder(compoundSetup, loweredBevel);
TitledBorder topFrameTitle = BorderFactory.createTitledBorder(compoundFinal, "Stuff");
topFrameTitle.setTitleJustification(TitledBorder.CENTER);
pnl.setBorder(topFrameTitle);
pnl.setLayout(new GridBagLayout());
pnl.setOpaque(false);
return pnl;
}
//**************************************************************************************
public static void main(String[] args) {
new TestGui();
}
}
注意:我使用的是自定義渲染器。 這是代碼......
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class ComboBoxRenderer extends JLabel implements ListCellRenderer
{
private Color selectionBackgroundColor;
private DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
// Constructor
public ComboBoxRenderer()
{
setOpaque(true);
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
selectionBackgroundColor = this.dlcr.getBackground(); // Have to set a color, else a compiler error will occur
}
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
{
// Set the list background color to default color (default color will show once selection is made)
setBackground(list.getBackground());
Color mouseHoverHighlight = Color.LIGHT_GRAY;
setText((String)value);
// Check which item is selected
if(isSelected)
{
// Set background color of the item your cursor is hovering over to the original background color
setBackground(mouseHoverHighlight);
}
else
{
// Set background to specific color depending on text value
String selectedTextInDropdownList = getText();
if (selectedTextInDropdownList.equals("SelectedTextOne")) {
setBackground(Color.GREEN);
} else if (selectedTextInDropdownList.equals("SelectedTextTwo")) {
setBackground(Color.RED);
} else {
setBackground(this.dlcr.getBackground());
}
}
String selectedText = getText();
if (selectedText.equals("SelectedTextOne")){
list.setSelectionBackground(Color.GREEN);
} else if (selectedText.equals("SelectedTextTwo")){
list.setSelectionBackground(Color.RED);
} else {
list.setSelectionBackground(this.dlcr.getBackground());
}
return this;
}
}
重現錯誤的步驟:
預期結果
你的方法是正確的,但是BasicComboBoxUI在你的方向盤中放了一個輻條。 幸運的是,我有一個技巧,這有助於避免這個問題。
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
@SuppressWarnings("unchecked")
public class ComboBgTest {
private static final String[] VALUES = {"One", "Two", "Three"};
@SuppressWarnings("serial")
public static void main(String[] args) {
JComboBox<String> cb = new JComboBox<>(VALUES);
cb.setSelectedItem(null);
cb.setRenderer(new BasicComboBoxRenderer() {
boolean ignoreBG = true;
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
ignoreBG = false;
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (index == -1) { // check whether we are render the item shown at top
if (VALUES[0].equals(value)) {
c.setBackground(Color.RED);
} else if (VALUES[1].equals(value)) {
setBackground(Color.GREEN);
} else if (VALUES[2].equals(value)) {
setBackground(Color.BLUE);
}
}
ignoreBG = true;
return this;
}
@Override
public void setBackground(Color bg) {
// ignore all BG which is set from outside.
if (!ignoreBG) {
super.setBackground(bg);
}
}
});
JFrame frm = new JFrame("Combo test");
frm.add(cb);
frm.pack();
frm.setLocationRelativeTo(null);
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setVisible(true);
}
}
PS同樣的方法也適用於字體和foregorund。
[rant]你真的必須學會將示例代碼降低到演示問題的最低要求,每次重構代碼需要花費很多精力:P [/ rant]
發生了什么, JComboBox
正在從列表中選擇(和渲染)后更改所選項目的背景顏色。 一種可能的解決方案是通過具有始終返回的“覆蓋”顏色來簡單地避免這種情況,例如,無論設置什么,...
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestGui extends JFrame {
private final String[] guiCharSel = {"--- Select Character ---", "SelectedTextOne", "SelectedTextTwo", "SelectedTextThree", "SelectedTextFour"};
public static void main(String[] args) {
new TestGui();
}
public TestGui() throws HeadlessException {
try {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JComboBox box = new JComboBox(guiCharSel);
box.setRenderer(new ComboBoxRenderer());
JTextField field = new JTextField(10);
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
frame.add(box, gbc);
frame.add(field, gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
class ComboBoxRenderer extends DefaultListCellRenderer {
private Color overrideBackground;
private Color mouseHoverHighlight = Color.LIGHT_GRAY;
// Constructor
public ComboBoxRenderer() {
setOpaque(true);
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
}
@Override
public void setOpaque(boolean isOpaque) {
System.out.println("setOpaque " + isOpaque);
//NOOP
}
@Override
public boolean isOpaque() {
return true;
}
@Override
public void setBackground(Color bg) {
System.out.println(">> Background = " + bg);
super.setBackground(bg); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Color getBackground() {
return overrideBackground == null ? super.getBackground() : overrideBackground;
}
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
// Set the list background color to default color (default color will show once selection is made)
overrideBackground = null;
setText((String) value);
// Check which item is selected
System.out.println(value + "; isSelected = " + isSelected + "; cellHasFocus = " + cellHasFocus);
if (isSelected) {
// Set background color of the item your cursor is hovering over to the original background color
setBackground(mouseHoverHighlight);
} else {
// Set background to specific color depending on text value
String selectedTextInDropdownList = getText();
if (selectedTextInDropdownList.equals("SelectedTextOne")) {
System.out.println(">> Green");
overrideBackground = Color.GREEN;
} else if (selectedTextInDropdownList.equals("SelectedTextTwo")) {
System.out.println(">> Red");
overrideBackground = Color.RED;
} else {
overrideBackground = null;
}
}
return this;
}
}
}
這只會在組合框丟失焦點后顯示,因為該項目已被渲染為“已選中”。 你也可以改變選擇背景,但我找不到任何簡單的狀態組合
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.