自定义JComboBoxRenderer根据文本选择更改背景颜色

问题描述:

更新的问题

第1部分:最初,我首先要在选择一个项目后删除突出显示的选择(因为这会使选择的背景颜色混乱).我看到可以从此处完成此操作> 在JComboBox中删除突出显示-(已解决)

Part 1: Originally, I was first going to remove the highlight selection after an item has been selected (because this was messing up the background color for the selection made). I saw this could be done from here > Delete highlighting in JComboBox - (Solved)

第2部分:现在...我试图让它识别选定的文本,并根据需要更改背景颜色(选定时,而不是鼠标悬停在列表中的项目上时)选择了哪个文本.它的确会更改颜色以匹配文本,但是在选择另一个对象(取消选择组合框)时,背景颜色会变回默认值-(已解决-请参阅我的解决方案)

Part 2: Now... I'm trying to have it identify the selected text, and change the background color (when selected, and not when mouse hovers over item in list) depending on which text was selected. It does change the color to match the text, however when selecting another object (de-selecting the combobox), the background color changes back to the default - (Solved - See my solution)

第3部分:另外,我希望在下拉列表中显示文本的背景色(而不是将鼠标悬停在其上). -(已解决)

Part 3: Also, I would like to have the background color show for the text in the dropdown list (while the mouse is not being hovered over it). - (Solved)

这是代码...

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

另外...这是鼓起GUI的代码,以便您查看其行为方式...

Also... Here is the code to drum up a GUI so you can see how it is behaving...

Edit2 :编辑后的代码即可编译,而不会在图像中显示背景

Edited code to compile without background shown in images

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

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


重现问题的步骤:

点击选择字符"组合框

在列表中单击"selectedTextOne"项. Note: "selectedTextThree" is only a different color because my mouse is hovered over it. This is behaving properly.

Click the "selectedTextOne" item in the list. Note: "selectedTextThree" is only a different color because my mouse is hovered over it. This is behaving properly.

单击按钮. Note: the button doesn't actually do anything, we just do this so the combo box is no longer selected.

请注意组合框如何从绿色变为灰色(我们希望它保持绿色).

Notice how the combo box changes from green to gray (we want it to stay green).

有人知道如何确保为文本值的颜色设置背景色(在组合框本身而不是列表中)吗?

Anyone have any idea how to make sure the background color(in the combo box itself and not the list) is set for the color of the text value?

我终于找到了正确的组合.这是代码...

I finally found the right combination. Here is the code...

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

class ComboBoxRenderer extends JLabel implements ListCellRenderer
{
    private Color selectionBackgroundColor;
    private Color defaultBackgroundColor;
    private DefaultListCellRenderer dlcr = new DefaultListCellRenderer();

    // Constructor
    public ComboBoxRenderer()
    {
        setOpaque(true);
        setHorizontalAlignment(CENTER);
        setVerticalAlignment(CENTER);
        defaultBackgroundColor = 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)
        selectionBackgroundColor = null;
        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
            String selectedText = getText();
            if (selectedText.equals("SelectedTextOne")){
                list.setSelectionBackground(Color.GREEN);
            } else if (selectedText.equals("SelectedTextTwo")){
                list.setSelectionBackground(Color.RED);
            } else {
                list.setSelectionBackground(defaultBackgroundColor);
            }
            setBackground(mouseHoverHighlight);
        }
        else
        {
            // Set background to specific color depending on text value
            String selectedTextInDropdownList = getText();
            if (selectedTextInDropdownList.equals("SelectedTextOne")) {
                selectionBackgroundColor = Color.GREEN;
            } else if (selectedTextInDropdownList.equals("SelectedTextTwo")) {
                selectionBackgroundColor = Color.RED;
            } else {
                selectionBackgroundColor = defaultBackgroundColor;
            }
        }


        return this;
    }

    @Override
    public boolean isOpaque() {
        return true;
    }

    @Override
    public void setBackground(Color bg) {
        super.setBackground(bg); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public Color getBackground() {
        return selectionBackgroundColor == null ? super.getBackground() : selectionBackgroundColor;
    }
}