Java 覆盖光晕颜色

Java 覆盖光晕颜色,java,swing,look-and-feel,swingx,nimbus,Java,Swing,Look And Feel,Swingx,Nimbus,我们正在使用Nimbus LaF开发Swing应用程序。我们已经更改了许多Nimbus默认设置(控件、文本、NimbusLightBackground等),使其具有暗主题 现在我们在JLists和jComboxes的渲染方面遇到了很大的麻烦,因为渲染器显然使用了NimbusLightBackground颜色作为所选文本的前景。这导致深蓝色背景上出现深灰色文本-不好 我已尝试通过UIManager.putDefault()和每个组件覆盖全局覆盖Nimbus默认值(“ComboBox:\”Combo

我们正在使用Nimbus LaF开发Swing应用程序。我们已经更改了许多Nimbus默认设置(控件、文本、NimbusLightBackground等),使其具有暗主题

现在我们在JLists和jComboxes的渲染方面遇到了很大的麻烦,因为渲染器显然使用了NimbusLightBackground颜色作为所选文本的前景。这导致深蓝色背景上出现深灰色文本-不好

我已尝试通过UIManager.putDefault()和每个组件覆盖全局覆盖Nimbus默认值(“ComboBox:\”ComboBox.listRenderer\“[Selected].textForeground”等)中任何适用的外观键,但根本无法获得任何更改

即使是SwingX Highlighter似乎也无法覆盖这种行为,至少在combobox下拉列表中是如此

关于如何为J(X)列表和J(X)组合框下拉列表设置所选文本的前景色有什么想法吗

我最近一次尝试每个组件覆盖:

JXComboBox comboBox = new JXComboBox();
UIDefaults comboBoxTheme = new UIDefaults();
comboBoxTheme.put("nimbusLightBackground", new Color(0xFFFAFA));
comboBoxTheme.put("ComboBox:\"ComboBox.listRenderer\"[Selected].textForeground", new Color(0xFFFAFA));
comboBox.putClientProperty("Nimbus.Overrides.InheritDefaults", true);
comboBox.putClientProperty("Nimbus.Overrides", comboBoxTheme);
SwingUtilities.updateComponentTreeUI(comboBox);
应用程序范围内的nimbus默认值为:

ColorUIResource backgroundUI = new ColorUIResource(0x494949);
ColorUIResource textUI = new ColorUIResource(0xFFFAFA);
ColorUIResource controlBackgroundUI = new ColorUIResource(0x5F5F4D);
ColorUIResource infoBackgroundUI = new ColorUIResource(0x2f5cb4);
ColorUIResource infoUI = new ColorUIResource(0x2f5cb4);
ColorUIResource lightBackgroundUI = new ColorUIResource(0x5D5D5B);
ColorUIResource focusUI = new ColorUIResource(0x39698a);

UIManager.put("control", backgroundUI);
UIManager.put("text", textUI);
UIManager.put("nimbusLightBackground", lightBackgroundUI);
UIManager.put("info", infoUI);
UIManager.put("nimbusInfoBlue", infoBackgroundUI);
UIManager.put("nimbusBase", controlBackgroundUI);
UIManager.put("nimbusBlueGrey", controlBackgroundUI);
UIManager.put("nimbusFocus", focusUI);
所有这些都是在Java7U55中实现的,尽管我怀疑这一点,因为似乎有相当一段时间没有人维护Swing/Nimbus

附言:我当然读过一些书和其他书,但还没有找到一个有效的答案

编辑:这里有一个SSCCE演示了这个问题。它创建了一个JFrror,其中只有一个默认的组合框在顶部,中间的列表和底部的每个组件的组合框。在列表中或从下拉框中选择值时可以看到问题

package sscce;

import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.plaf.ColorUIResource;

public class ForegroundProblemDemo extends JFrame {

public ForegroundProblemDemo() {
    super("Demo");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JComboBox<String> comboBoxWithDefaults = createComboBox();
    JComboBox<String> comboBoxWithOverrides = createComboBox();
    JList<String> list = createList();
    addOverrides(comboBoxWithOverrides);

    getContentPane().setLayout(new BorderLayout());
    getContentPane().add(new JScrollPane(list), BorderLayout.CENTER);
    getContentPane().add(comboBoxWithDefaults, BorderLayout.NORTH);
    getContentPane().add(comboBoxWithOverrides, BorderLayout.SOUTH);

    pack();
    setLocationRelativeTo(null);
    setVisible(true);
}

JComboBox<String> createComboBox() {
    JComboBox<String> comboBox = new JComboBox<>(new String[] {"A","B","C","D"});
    return comboBox;
}

JList<String> createList() {
    JList<String> list = new JList<>(new String[] {"A","B","C","D"});
    return list;
}

void addOverrides(JComponent component) {
    UIDefaults theme = new UIDefaults();
    theme.put("nimbusLightBackground", new Color(0xFFFAFA));
    theme.put("ComboBox:\"ComboBox.listRenderer\"[Selected].textForeground", new Color(0xFFFAFA));
    component.putClientProperty("Nimbus.Overrides.InheritDefaults", true);
    component.putClientProperty("Nimbus.Overrides", theme);
    SwingUtilities.updateComponentTreeUI(component);
}


public static void main(String... args) throws Throwable {
    ColorUIResource backgroundUI = new ColorUIResource(0x494949);
    ColorUIResource textUI = new ColorUIResource(0xFFFAFA);
    ColorUIResource controlBackgroundUI = new ColorUIResource(0x5F5F4D);
    ColorUIResource infoBackgroundUI = new ColorUIResource(0x2f5cb4);
    ColorUIResource infoUI = new ColorUIResource(0x2f5cb4);
    ColorUIResource lightBackgroundUI = new ColorUIResource(0x5D5D5B);
    ColorUIResource focusUI = new ColorUIResource(0x39698a);
    UIManager.put("control", backgroundUI);
    UIManager.put("text", textUI);
    UIManager.put("nimbusLightBackground", lightBackgroundUI);
    UIManager.put("info", infoUI);
    UIManager.put("nimbusInfoBlue", infoBackgroundUI);
    UIManager.put("nimbusBase", controlBackgroundUI);
    UIManager.put("nimbusBlueGrey", controlBackgroundUI);
    UIManager.put("nimbusFocus", focusUI);

    for (LookAndFeelInfo lafInfo : UIManager.getInstalledLookAndFeels()) {
        if ("Nimbus".equals(lafInfo.getName())) {
            UIManager.setLookAndFeel(lafInfo.getClassName());
            break;
        }
    }

    new ForegroundProblemDemo();
}

}
封装sscce;
导入java.awt.BorderLayout;
导入java.awt.Color;
导入javax.swing.JComboBox;
导入javax.swing.JComponent;
导入javax.swing.JFrame;
导入javax.swing.JList;
导入javax.swing.JScrollPane;
导入javax.swing.SwingUtilities;
导入javax.swing.ui默认值;
导入javax.swing.UIManager;
导入javax.swing.UIManager.LookAndFeelInfo;
导入javax.swing.plaf.ColorUIResource;
公共类ForegroundProblemDemo扩展JFrame{
公共前景问题演示(){
超级(“演示”);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComboBox ComboxWithDefaults=createComboBox();
JComboBox ComboBox WithOverrides=createComboBox();
JList list=createList();
添加覆盖(comboBoxWithOverrides);
getContentPane().setLayout(新的BorderLayout());
getContentPane().add(新的JScrollPane(列表),BorderLayout.CENTER);
getContentPane().add(comboBoxWithDefaults,BorderLayout.NORTH);
getContentPane().add(comboBoxWithOverrides,BorderLayout.SOUTH);
包装();
setLocationRelativeTo(空);
setVisible(真);
}
JComboBox createComboBox(){
JComboBox组合框=新的JComboBox(新字符串[]{“A”、“B”、“C”、“D”});
返回组合框;
}
JList createList(){
JList list=newjlist(新字符串[]{“A”、“B”、“C”、“D”});
退货清单;
}
void addOverrides(JComponent组件){
UIDefaults主题=新的UIDefaults();
主题放置(“nimbusLightBackground”,新颜色(0xFFFAFA));
theme.put(“ComboBox:\”ComboBox.listRenderer\”[Selected].textForeground],新颜色(0xFFFAFA));
component.putClientProperty(“Nimbus.Overrides.InheritDefaults”,true);
component.putClientProperty(“Nimbus.Overrides”,主题);
SwingUtilities.updateComponentTreeUI(组件);
}
publicstaticvoidmain(字符串…参数)抛出Throwable{
ColorUIResource backgroundUI=新的ColorUIResource(0x4949);
ColorUIResource textUI=新的ColorUIResource(0xFFFAFA);
ColorUIResource controlBackgroundUI=新的ColorUIResource(0x5F5F4D);
ColorUIResource infoBackgroundUI=新的ColorUIResource(0x2f5cb4);
ColorUIResource infoUI=新的ColorUIResource(0x2f5cb4);
ColorUIResource lightBackgroundUI=新的ColorUIResource(0x5D5D5B);
ColorUIResource focusUI=新的ColorUIResource(0x39698a);
UIManager.put(“控制”,背景UI);
UIManager.put(“文本”,textUI);
UIManager.put(“nimbusLightBackground”,lightBackgroundUI);
UIManager.put(“信息”,infoUI);
UIManager.put(“nimbusInfoBlue”,infoBackgroundUI);
UIManager.put(“nimbusBase”,controlBackgroundUI);
UIManager.put(“nimbusBlueGrey”,controlBackgroundUI);
UIManager.put(“nimbusFocus”,focusUI);
for(LookAndFeelInfo-lafInfo:UIManager.getInstalledLookAndFeels()){
if(“Nimbus”.equals(lafInfo.getName())){
UIManager.setLookAndFeel(lafInfo.getClassName());
打破
}
}
新的前沿问题demo();
}
}

编辑2:抱歉,之前应该提到这一点:对于列表,使用setSelectionForeground()方法可以轻松解决问题。对于组合框,我还没有找到缺少自定义渲染器的方法。所以我主要关注的是组合框。

我不喜欢这个答案,我很乐意接受任何一个告诉我如何使用Nimbus设置的答案。

我最终所做的是——如果我找到更好的解决方案,我将乐于改变——这是:

我创建了一个ListCellRenderer实现,它包装了DefaultListCellRenderer,并在isSelected参数为true时设置前景颜色。它可以工作,但我一点也不喜欢它,原因如下:

  • 其他所有自定义渲染器(谢天谢地不是很多)都必须实现相同的hack,这违反了DRY原则
  • 这会覆盖LookAndFeel,这样设置另一个主题(或者简单地更改回light主题)将需要在代码中的多个位置进行更改
  • JList或JComboBox的每个实例都必须手动设置渲染器,这再次违反了DRY原则
  • 对于Java核心库中的一个bug来说,这是一个难看的解决方法,尽管有多个关于该主题的bug报告,但自2007年以来似乎什么都没有发生,我对此感到愤怒 不管怎样,这里的代码为那些孤独的流浪者谁可能有同样的问题

    import java.awt.Color;
    import java.awt.Component;
    
    import javax.swing.DefaultListCellRenderer;
    import javax.swing.JList;
    import javax.swing.ListCellRenderer;
    
    
    @SuppressWarnings("rawtypes")
    public class ThemeCompliantListCellRenderer implements ListCellRenderer {
    
    private ListCellRenderer wrappedRenderer = new DefaultListCellRenderer();
    private Color textColor = new Color(0xFFFAFA); 
    
    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        @SuppressWarnings("unchecked")
        Component c = wrappedRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        if (isSelected) {
            c.setForeground(textColor);
        }
        return c;
    }
    
    public void setSelectedForeground(Color color) {
        textColor = color;
    }
    }
    

    我不喜欢这个答案,如果有人告诉我如何使用Nimbus设置,我会欣然接受。

    什么
    import java.awt.*;
    import java.util.Vector;
    import javax.swing.*;
    import javax.swing.UIManager;
    import javax.swing.plaf.ColorUIResource;
    import javax.swing.plaf.nimbus.AbstractRegionPainter;
    
    public class MyComboBox {
    
        private Vector<String> listSomeString = new Vector<String>();
        private JComboBox someComboBox = new JComboBox(listSomeString);
        private JComboBox editableComboBox = new JComboBox(listSomeString);
        private JComboBox non_EditableComboBox = new JComboBox(listSomeString);
        private JFrame frame;
    
        public MyComboBox() {
            listSomeString.add("-");
            listSomeString.add("Snowboarding");
            listSomeString.add("Rowing");
            listSomeString.add("Knitting");
            listSomeString.add("Speed reading");
            someComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            someComboBox.setFont(new Font("Serif", Font.BOLD, 16));
            someComboBox.setEditable(true);
            someComboBox.getEditor().getEditorComponent().setBackground(Color.YELLOW);
            ((JTextField) someComboBox.getEditor().getEditorComponent()).setBackground(Color.YELLOW);
            editableComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            editableComboBox.setFont(new Font("Serif", Font.BOLD, 16));
            editableComboBox.setEditable(true);
            JTextField text = ((JTextField) editableComboBox.getEditor().getEditorComponent());
            text.setBackground(Color.YELLOW);
            /*JComboBox coloredArrowsCombo = editableComboBox;
             Component[] comp = coloredArrowsCombo.getComponents();
             for (int i = 0; i < comp.length; i++) {
             if (comp[i] instanceof MetalComboBoxButton) {
             MetalComboBoxButton coloredArrowsButton = (MetalComboBoxButton) comp[i];
             coloredArrowsButton.setBackground(null);
             break;
             }
             }*/
            non_EditableComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            non_EditableComboBox.setFont(new Font("Serif", Font.BOLD, 16));
            frame = new JFrame();
            frame.setLayout(new GridLayout(0, 1, 10, 10));
            frame.add(someComboBox);
            frame.add(editableComboBox);
            frame.add(non_EditableComboBox);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLocation(100, 100);
            frame.pack();
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            try {
                for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
                    if ("Nimbus".equals(laf.getName())) {
                        UIManager.setLookAndFeel(laf.getClassName());
                        UIManager.getLookAndFeelDefaults().put("ComboBox[Enabled].backgroundPainter",
                                new javax.swing.plaf.nimbus.AbstractRegionPainter() {
                            @Override
                            protected AbstractRegionPainter.PaintContext getPaintContext() {
                                return new AbstractRegionPainter.PaintContext(null, null, false);
                            }
    
                            @Override
                            protected void doPaint(Graphics2D g, JComponent c,
                                    int width, int height, Object[] extendedCacheKeys) {
                                g.setColor(Color.MAGENTA);
                                g.fill(new Rectangle(0, 0, width, height));
                            }
                        });
                        UIManager.getLookAndFeelDefaults().put("ComboBox[Focused+Pressed].backgroundPainter",
                                new javax.swing.plaf.nimbus.AbstractRegionPainter() {
                            @Override
                            protected AbstractRegionPainter.PaintContext getPaintContext() {
                                return new AbstractRegionPainter.PaintContext(null, null, false);
                            }
    
                            @Override
                            protected void doPaint(Graphics2D g, JComponent c,
                                    int width, int height, Object[] extendedCacheKeys) {
                                g.setColor(Color.CYAN);
                                g.fill(new Rectangle(0, 0, width, height));
                            }
                        });
                        UIManager.getLookAndFeelDefaults().put("ComboBox[Focused].backgroundPainter",
                                new javax.swing.plaf.nimbus.AbstractRegionPainter() {
                            @Override
                            protected AbstractRegionPainter.PaintContext getPaintContext() {
                                return new AbstractRegionPainter.PaintContext(null, null, false);
                            }
    
                            @Override
                            protected void doPaint(Graphics2D g, JComponent c,
                                    int width, int height, Object[] extendedCacheKeys) {
                                g.setColor(Color.RED);
                                g.fill(new Rectangle(0, 0, width, height));
                            }
                        });
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    MyComboBox aCTF = new MyComboBox();
                }
            });
        }
    }
    
    import java.awt.*;
    import java.util.Vector;
    import javax.swing.*;
    import javax.swing.UIManager;
    
    public class MyComboBox {
    
        private Vector<String> listSomeString = new Vector<String>();
        private JComboBox someComboBox = new JComboBox(listSomeString);
        private JComboBox editableComboBox = new JComboBox(listSomeString);
        private JComboBox non_EditableComboBox = new JComboBox(listSomeString);
        private JFrame frame;
    
        public MyComboBox() {
            listSomeString.add("-");
            listSomeString.add("Snowboarding");
            listSomeString.add("Rowing");
            listSomeString.add("Knitting");
            listSomeString.add("Speed reading");
            someComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            someComboBox.setFont(new Font("Serif", Font.BOLD, 16));
            someComboBox.setEditable(true);
            someComboBox.getEditor().getEditorComponent().setBackground(Color.YELLOW);
            ((JTextField) someComboBox.getEditor().getEditorComponent()).setBackground(Color.YELLOW);
            editableComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            editableComboBox.setFont(new Font("Serif", Font.BOLD, 16));
            editableComboBox.setEditable(true);
            JTextField text = ((JTextField) editableComboBox.getEditor().getEditorComponent());
            text.setBackground(Color.YELLOW);
            non_EditableComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            non_EditableComboBox.setFont(new Font("Serif", Font.BOLD, 16));
            frame = new JFrame();
            frame.setLayout(new GridLayout(0, 1, 10, 10));
            frame.add(someComboBox);
            frame.add(editableComboBox);
            frame.add(non_EditableComboBox);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLocation(100, 100);
            frame.pack();
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            try {
                UIManager.setLookAndFeel("com.seaglasslookandfeel.SeaGlassLookAndFeel");
            } catch (Exception e) {
                e.printStackTrace();
            }
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    MyComboBox aCTF = new MyComboBox();
                }
            });
        }
    }