【问题标题】:Color of the dropdown control and border in an uneditable JComboBox不可编辑的 JComboBox 中下拉控件和边框的颜色
【发布时间】:2010-12-29 20:21:25
【问题描述】:

不可编辑的 JComboBox 中选中项的背景颜色是一种蓝色:

我知道您可以将其更改为其他颜色,例如白色,例如使用following code

jComboBox1.setRenderer(new DefaultListCellRenderer() {
    @Override
    public void paint(Graphics g) {
        setBackground(Color.WHITE);
        setForeground(Color.BLACK);
        super.paint(g);
    }
});

这给了你这样的东西:

但是,如果您双击该组合框,其中一些会变为灰色(带有三角形和边框的部分):

有没有办法阻止这些部分在双击时变灰?

请注意,如果你先调用 super.paint(),整个事情都会变暗(包括“Select...”后面的部分),所以这无济于事。

【问题讨论】:

  • 如果先调用 super.paint() 会发生什么?
  • 没有帮助。实际上使情况变得更糟。请参阅我对问题的编辑。
  • SSCCE (sscce.org) 比图片更好。无论您单击还是双击组合框,我都没有看到任何区别。箭头永远不会是清晰的白色背景,也永远不会变成深灰色背景。双击对我来说就是打开和关闭下拉菜单。我不知道为什么您的测试代码与我的不同,所以我无法提供任何建议。

标签: java swing jcombobox


【解决方案1】:

不确定 OP 究竟想要实现什么,但这是我的 JComboBox 着色配方:

static public void main(String[] args) {
    JFrame window = new JFrame("Coloring ComboBox");
    window.setSize(170, 150);
    window.setLocationRelativeTo(null);
    window.setLayout(null);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //---textArea is just for focus switching
    JTextArea textArea = new JTextArea();
    textArea.setBounds(5, 5, 140, 25);
    window.add(textArea);

    UIManager.put("ComboBox.selectionBackground", Color.magenta); //---focused background color
    //---see comboBox's UIDefaults for more tweaks

    JComboBox<String> coloredCombo = new JComboBox<String>(new String[]{"Dog", "Cat", "Bird"});
    coloredCombo.setEditable(false);
    coloredCombo.setUI(new BasicComboBoxUI() {
            @SuppressWarnings({"serial"})
            @Override
            protected ComboPopup createPopup() {
                return new BasicComboPopup(coloredCombo) {
                    {
                        //---style popup anyway you like
                        this.setBorder(BorderFactory.createLineBorder(Color.green, 2));//---popup's border color
                    }
                };
            }
            @Override
            protected JButton createArrowButton() {
                //---style arrow button anyway you like
                JButton result = new JButton();
                result.setBackground(Color.orange);//---button's color
                return result;
            }
        });

    coloredCombo.setBorder(BorderFactory.createLineBorder(Color.red, 2));//---border color
    coloredCombo.setBackground(Color.yellow); //---not focused background color

    coloredCombo.setRenderer(new ListCellRenderer<String>() {
        @Override
        public Component getListCellRendererComponent(JList<? extends String> list, String value, int index,
                boolean isSelected, boolean cellHasFocus) {
            JLabel result = new JLabel(value);
            result.setOpaque(true);
            result.setBackground(isSelected ? Color.cyan : Color.blue); //---item background color
            return result;
        }
    });
    coloredCombo.setBounds(5, 35, 140, 25);
    window.add(coloredCombo);

    window.setVisible(true);
}

当然,这只是一个例子,我建议你创建一个花哨的自定义类来重用。

【讨论】:

    【解决方案2】:

    几件事:

    1. 组合框的外观(显示区域、箭头、下拉菜单)取决于 LAF。您的屏幕截图建议使用 WinXP。如果您必须支持任何其他 LAF,请务必对其进行测试,因为适用于一个 LAF 的方法可能不适用于另一个 LAF。我发现 JComboBoxes 尤其如此。

    2. 就像 Twister 建议的那样,通过覆盖 paint() 方法来更改颜色可能不是最好的方法。只需设置组合框本身的背景/前景色。如果您想更改下拉菜单的颜色 本身(我不清楚您是否要这样做),然后添加一个覆盖 getListCellRendererComponent 的自定义渲染器来设置背景/前景。

      public static class CustomRenderer extends DefaultListCellRenderer {
      
      @Override
      public Component getListCellRendererComponent(JList list, Object value,
              int index, boolean isSelected, boolean cellHasFocus) {
          super.getListCellRendererComponent(list, value, index, isSelected,
                  cellHasFocus);
          setBackground(Color.WHITE);
          setForeground(Color.BLACK);     
          return this;
      }       
      

      }

    3. 灰色三角形和边框的出现是因为组合框现在有了焦点。你可以让它不能聚焦,颜色就会消失。然而,这可能不是您想要的行为。

      JComboBox combo = new JComboBox(new Object[]{"Dog", "Cat", "Bird"});
      combo.setBackground(Color.WHITE);
      combo.setForeground(Color.BLACK);
      combo.setFocusable(false);
      

    【讨论】:

      【解决方案3】:

      首先,您不应该在paint方法中设置前景和背景。您应该覆盖渲染器的 getListCellRendererComponent 以便对其进行自定义。如果您拥有焦点或选择了默认渲染器,则默认渲染器会更改其外观。如果您不希望这些功能重新实现该方法。

      然后,如果您向渲染器添加线边框 (setBorder(BorderFactory.createLineBorder(Color.black)),您将看到绘制的不是渲染器的一部分,而是组合框本身。因此您可能需要自定义界面

      【讨论】:

        【解决方案4】:

        swing 代码调用getListCellRendererComponent,然后在返回的组件上调用setForegroundsetBackground(取决于组件是否被选中和/或聚焦)。我认为这是针对某些遗留行为。不幸的是,它违背了我在渲染器中设置它的目的。

        我用这种方法取得了一些不错的效果:

        下面的代码通过覆盖 fg/bg 设置器什么都不做来绕过更改前景和背景,然后我只是调用超级实现来设置我想要的颜色。

        public static class CustomRenderer extends DefaultListCellRenderer {
            public Component getListCellRendererComponent(JList list, Object value,
                int index, boolean isSelected, boolean cellHasFocus) {
                super.getListCellRendererComponent(list, value, index, isSelected,
                    cellHasFocus);
                super.setBackground(Color.WHITE);
                super.setForeground(Color.BLACK);     
                return this;
            }
            public void setForeground(Color c) {}
            public void setBackground(Color c) {}
        }
        

        附录: 灰色边框可能就是这样,一个边框。尝试相同的方法,但也要覆盖setBorder

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-05-02
          • 2015-11-19
          • 2011-05-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-29
          相关资源
          最近更新 更多