我们正在使用Nimbus LaF开发Swing应用程序。我们更改了许多Nimbus默认设置(控件,文本,NimbusLightBackground等)以使主题变暗。
现在我们在渲染JLists和JComboBox时遇到了很大的麻烦,因为渲染器显然使用了NimbusLightBackground颜色来选择文本前景。这导致深蓝色背景上的深灰色文本 - 不好。
我尝试通过UIManager全局覆盖Nimbus Defaults中的任何适用的键(" ComboBox:\" ComboBox.listRenderer \" [Selected] .textForeground"等等) .putDefault()和per-component-overrides,但根本无法获得任何更改。
即使SwingX荧光笔似乎也无法覆盖此行为,至少在组合框下拉列表中。
有关如何为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);
所有这些都是在Java 7u55中实现的,尽管我怀疑这一点并不重要,因为似乎没有人维持Swing / Nimbus很长一段时间。
PS:我当然读过this question和其他人,但是没有找到有效的答案。
编辑:这是一个证明问题的SSCCE。它创建了一个JFrame,顶部有一个默认的组合框,中间是一个列表,底部是一个按组件覆盖的组合框。选择列表中的值或从框下拉列表中可以看到问题。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。
答案 0 :(得分:2)
我不喜欢这个答案,很乐意接受任何告诉我如何使用Nimbus设置
的人我最终做了什么 - 如果我找到更好的解决方案,我将很高兴改变 - 是这样的:
我创建了一个ListCellRenderer实现,它包装了DefaultListCellRenderer,并且如果isSelected参数为true,则设置前景色。它有效,但由于以下原因我不喜欢它:
无论如何,这里是那些可能有同样问题的孤独流浪者的代码。
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;
}
}
答案 1 :(得分:2)
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就没有任何事情发生,那么可以为可编辑和不可编辑的JComboBox创建漂亮的主题(具有相同的Color主题)
我会看看Seaglas L&amp; F(注意要求在JDK 1.6._Xxx中编译)
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();
}
});
}
}