首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >覆盖Nimbus颜色

覆盖Nimbus颜色
EN

Stack Overflow用户
提问于 2014-06-12 08:23:43
回答 2查看 2.4K关注 0票数 2

我们正在使用Nimbus LaF开发Swing应用程序。我们已经将许多Nimbus默认值(控件、文本、NimbusLightBackground等)更改为有一个暗主题。

现在我们在渲染JLists和JComboBoxes时遇到了很大的困难,因为渲染器显然使用NimbusLightBackground颜色来显示选定的文本前景。这将导致深蓝色背景上的深灰色文本--不太好。

我尝试过通过("ComboBox:\"ComboBox.listRenderer\"Selected.textForeground“()和每个组件覆盖全局地覆盖Nimbus默认值中的任何可应用的键,比如UIManager.putDefault()和其他类似的,但是根本无法得到任何更改。

即使是SwingX荧光笔似乎也不能覆盖这种行为,至少在组合框下拉列表中是这样的。

对于如何为J(X)列表和J(X)下拉列表设置选定的文本前景颜色有什么想法吗?

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

代码语言:javascript
复制
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默认设置为:

代码语言:javascript
复制
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);

所有这些都是用Java 7u55实现的,不过我怀疑这一点,因为似乎没有人维护Swing/Nimbus相当一段时间。

PS:当然,我读过这个问题和其他书,但是没有找到一个有效的答案。

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

代码语言:javascript
复制
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();
}

}

编辑2:对不起,应该在前面提到这一点:对于列表,问题很容易用setSelectionForeground()方法解决。对于ComboBoxes,我还没有找到一条缺少自定义渲染器的方法。所以我主要关注的是ComboBoxes。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-06-13 07:54:12

  • 看看发生了什么,Win8.1 8.1 64b,Java7,JDK 1.7_021,通过使用完整的矩形画,

代码语言:javascript
复制
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();
            }
        });
    }
}
  • 如果不使用XxxRenderer,什么事情都不会发生,那么就有可能为可编辑和non_editable JComboBox创建漂亮的主题(具有相同的颜色主题)。
  • 我会看到SeaglaL&F(在JDK 1.6._Xxx中编译所需的注意事项)。

代码语言:javascript
复制
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();
            }
        });
    }
}
票数 2
EN

Stack Overflow用户

发布于 2014-06-13 06:51:10

我不喜欢这个答案,我很乐意接受任何告诉我它是如何与的设置一起工作的答案。

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

我已经创建了一个ListCellRenderer实现,它封装DefaultListCellRenderer并设置前景颜色,如果isSelected参数是真的话。它起作用,但我一点也不喜欢它,因为这些原因:

  1. 其他自定义渲染器(谢天谢地不多)都必须实现相同的攻击,这违反了DRY原则。
  2. 这将覆盖LookAndFeel,使设置另一个主题(或简单地将主题改为轻量级主题)将需要在代码中的多个位置进行更改。
  3. JList或JComboBox的每个实例都必须手动设置渲染器,这再次违反了DRY原则。
  4. 对于Java核心库中的一个bug来说,这是一个丑陋的解决办法,尽管有多个bug报告了这个主题,但我感到非常愤怒,自2007年以来似乎什么也没有发生过。

不管怎么说,这是那些可能有同样问题的孤独流浪者的代码。

代码语言:javascript
复制
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;
}
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24179643

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档