【问题标题】:JComboBox setBackground() without changing the color of the arrowJComboBox setBackground() 不改变箭头颜色
【发布时间】:2017-04-27 15:21:34
【问题描述】:

我已经尝试了 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;
    }
}

重现错误的步骤:

预期结果

【问题讨论】:

  • 您能否更好地描述您正在寻找的行为是什么?我知道你不希望箭头改变颜色,但你实际上想做什么?另外,如果您可以编辑该程序以便我们可以更轻松地运行它,那就太好了。我可以通过删除一些代码来运行它,比如对BackgroundPanel 的引用,但是如果我们可以将它粘贴到编辑器中,这对我们来说很好。 (不幸的是,我使用的是 Mac,所以我实际上无法帮助您解决您遇到的问题。Mac 不会为箭头着色,因为它们对 LAF 有更具体的样式。)
  • 实际上,我想我能够用金属 LAF 重现它。您是否有理由希望在执行的操作方法中调用charCombo.setBackground(...)?渲染器的颜色应该显示出来,所以我认为您不需要在组合框本身上设置背景。在组合框上设置背景似乎是改变箭头颜色的原因。
  • “您是否有理由希望在执行的操作方法中调用 charCombo.setBackground(...)?”。是的,原因在这里列出>stackoverflow.com/questions/43646234/…
  • 另外,对背景感到抱歉,这是我喜欢尝试在堆栈溢出时复制/过去的测试代码。我将删除该部分,因为它不再需要。

标签: java swing


【解决方案1】:

您的方法是正确的,但 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);
    }
}

附:同样的方法也适用于字体和前景。

【讨论】:

  • 不得不将行 JComboBox&lt;String&gt; cb = new JComboBox&lt;&gt;(VALUES); 更改为 JComboBox cb = new JComboBox(VALUES);。除此之外,它似乎正在工作。稍后当我完成当前任务以使用相同的逻辑时,我将对其进行剖析。谢谢:)
  • @FiddleFreak 可能您使用的是非常旧的 Java 版本。这段代码是用 Java 7 编译和测试的。
  • Opps,刚刚发布我们使用相同的基本解决方案:P
  • 使用 java 8,这个解决方案的另一个问题是它添加了选定的突出显示(删除背景颜色),并删除了下拉列表中的颜色。尝试不同的事情......(似乎会根据 ignoreBG 的变化来改变行为,只需要得到正确的组合)
  • @FiddleFreak 您可以删除行 if (index == -1) { 和相应的右大括号。在这种情况下,着色也适用于下拉列表
【解决方案2】:

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

这只会在组合框失去焦点后显示,因为该项目被呈现为“选定”。你也可以随意更改选择背景,但我找不到任何简单的状态组合

【讨论】:

    猜你喜欢
    • 2016-06-26
    • 1970-01-01
    • 2021-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-05
    • 1970-01-01
    相关资源
    最近更新 更多