问题
I want to use a different background color for all my JPanels in an application. How can I do that when using Nimbus Look and Feel?
I follow Changing the Color Theme to change the color of components in Nimbus Look and Feel.
It only works sometimes, randomly. If I set a PropertyChagneListener
before I change the color, it is only notified once.
Here is some test code:
public class RedPanels extends JFrame {
public RedPanels() {
JPanel panel = new JPanel();
add(panel);
setPreferredSize(new Dimension(100, 100));
pack();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
UIManager.getDefaults().addPropertyChangeListener(
new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
if (event.getPropertyName().equals("Panel.background")) {
System.out.println("color changed");
}
});
UIManager.put("Panel.background", new Color(255,0,0));
break;
}
}
} catch (Exception e) {
// Nimbus is not available.
}
new RedPanels();
}
});
}
}
回答1:
UIManager.getLookAndFeelDefaults().put("Panel.background", Color.RED);
回答2:
there are three ways
1) override nimbusBase
for set DerivedColor
2) create own Painter
, only one example is there -> aephyr codesource,
3) simple and dirty hack to set the Color directly
import java.awt.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class NimbusJPanelBackGround {
public NimbusJPanelBackGround() {
JPanel p = new JPanel();
UIDefaults nimbusOverrides = new UIDefaults();
nimbusOverrides.put("Panel.background", Color.blue);
p.putClientProperty("Nimbus.Overrides", nimbusOverrides);
SwingUtilities.updateComponentTreeUI(p);
JPanel p1 = new JPanel();
nimbusOverrides = new UIDefaults();
nimbusOverrides.put("Panel.background", Color.green);
p1.putClientProperty("Nimbus.Overrides", nimbusOverrides);
SwingUtilities.updateComponentTreeUI(p1);
p1.setBorder(new LineBorder(Color.black, 1));
JPanel p2 = new JPanel();
nimbusOverrides = new UIDefaults();
nimbusOverrides.put("Panel.background", Color.ORANGE);
p2.putClientProperty("Nimbus.Overrides", nimbusOverrides);
SwingUtilities.updateComponentTreeUI(p2);
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.add(p, BorderLayout.NORTH);
f.add(p1, BorderLayout.CENTER);
f.add(p2, BorderLayout.SOUTH);
f.setSize(200, 100);
f.setLocation(150, 150);
f.setVisible(true);
}
public static void main(String[] args) {
try {
for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(laf.getName())) {
UIManager.setLookAndFeel(laf.getClassName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
NimbusJPanelBackGround nimbusJPanelBackGround = new NimbusJPanelBackGround();
}
});
}
}
回答3:
Looks like a bug in jdk6, Panel.background one of the properties not taken. Following works in jdk7 (note the sequence: first set the color, then the LAF)
UIManager.put("Panel.background", new Color(255,0,0));
UIManager.setLookAndFeel(info.getClassName());
My guess is that it's still somehow buggy, as Nimbus is supposed to update its properties on receiving any change in the managers setting, so reversing the sequence to first set Nimbus, then put the color) should work as well, but doesn't even in jdk7
UIManager.setLookAndFeel(info.getClassName());
UIManager.put("Panel.background", new Color(255,0,0));
//UIManager.put("control", Color.MAGENTA);
Seems to be specific to Panel.background (and most probably a bunch of others), "control" is okay in both jdks, both before and after setting the LAF.
来源:https://stackoverflow.com/questions/8246589/how-to-change-the-background-color-for-jpanels-with-nimbus-look-and-feel