【问题标题】:custom JComboBoxRenderer change background color depending on text selection自定义 JComboBox 渲染器根据文本选择更改背景颜色
【发布时间】:2017-09-24 13:36:41
【问题描述】:

更新问题

第 1 部分: 最初,我首先要在选择项目后删除突出显示选择(因为这会弄乱所做选择的背景颜色)。我看到这可以从这里完成 > Delete highlighting in JComboBox - (已解决)

第 2 部分: 现在...我试图让它识别选定的文本,并根据选择了哪个文本。它确实改变了匹配文本的颜色,但是在选择另一个对象时(取消选择ComboBox),背景颜色会更改回默认值 - (已解决 - 请参阅我的解决方案)

第 3 部分:另外,我希望在下拉列表中显示文本的背景颜色(当鼠标没有悬停在它上面时)。 - (已解决)

这里是代码...

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 的代码,以便您查看它的行为...

Edit2:编辑后的代码在图像中不显示背景的情况下进行编译

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.

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

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

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

【问题讨论】:

    标签: java swing jcombobox


    【解决方案1】:

    所以,在玩了很多之后,这个...

    class ComboBoxRenderer extends JLabel implements ListCellRenderer {
    
        // Constructor
        public ComboBoxRenderer() {
            setOpaque(true);
            setHorizontalAlignment(CENTER);
            setVerticalAlignment(CENTER);
        }
    
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            Color mouseHoverHighlight = Color.LIGHT_GRAY;
            setBackground(list.getBackground());
            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 selectedText = getText();
                if (selectedText.equals("SelectedTextOne")) {
                    setBackground(Color.GREEN);
                } else if (selectedText.equals("SelectedTextTwo")) {
                    setBackground(Color.RED);
                }
            }
    
            // Do nothing about the text and font to be displayed
            setFont(list.getFont());
    
            return this;
        }
    }
    

    似乎有效。似乎在背景颜色引起问题之后设置文本,可能会触发重绘或其他什么。

    这就是我推荐使用DefaultListCellRenderer 的原因,它基于JLabel,并且已经过优化以减少此类更新

    【讨论】:

    • 到目前为止一切顺利,现在唯一的问题是在做出选择后,组合框仍以浅灰色突出显示(直到您选择其他内容)。知道如何解决这个问题吗?
    • 在我的测试中,它被外观(MacOS)覆盖。我还注意到 cellHasFocus 在您尝试从列表中选择值时是 false,但 true 在它是“选定”项目时,所以也许可以玩一下
    • 我更新了问题和代码,以便您可以看到我仍然遇到的问题。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2016-06-02
      • 2011-10-14
      • 1970-01-01
      • 1970-01-01
      • 2022-10-18
      • 2019-01-08
      • 2015-12-31
      • 2012-06-19
      • 1970-01-01
      相关资源
      最近更新 更多