动态更新LookAndFeel值

我希望能够动态更新我的Swing GUI的LookAndFeel属性。 在这种情况下,我有一个简单的Swing / Awt游戏,运行起初是Nimbus LookAndFeel 。 在启动后的不同时刻,我想改变(让我们说)一个细节:我的应用程序的背景颜色。

我可以通过这样做来改变背景颜色:

 for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { UIManager.setLookAndFeel(info.getClassName()); UIManager.getLookAndFeelDefaults().put("Panel.background", Color.RED); SwingUtilities.updateComponentTreeUI(SomeGame.this); break; } } 

这“工作”,因为应用程序的背景颜色正确更改,程序不会崩溃。 但是在命令行上我得到错误:

 Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at javax.swing.plaf.synth.SynthLookAndFeel.paintRegion(SynthLookAndFeel.java:371) at javax.swing.plaf.synth.SynthLookAndFeel.update(SynthLookAndFeel.java:335) 

事实上,某些东西是空的,但我无法弄清楚它是什么或如何解决它。 必须有一些我不理解的东西。 我查看了有关在Nimbus中设置背景颜色以及在启动后覆盖LookAndFeel信息的其他StackOverflow问题。

  • 当我调用getLookAndFeelDefaults() ,我还需要指定其余的默认值吗?
  • Java 1.6和1.7之间的工作方式有变化吗?

  • Java6的所有代码都必须更改Java7的Nimbus导入

  • Nimbus有一些惊喜,其中一个是可能的(没有肮脏的黑客,我正在为那些黑客留下评论)改变BackgroundJPanel只有一次

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

 import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.Color; import java.awt.AlphaComposite; import javax.swing.*; import javax.swing.UIManager.LookAndFeelInfo; import javax.swing.border.EmptyBorder; public class ButtonTest { private JFrame frame; private JPanel panel; private JButton opaqueButton1; private JButton opaqueButton2; private SoftJButton softButton1; private SoftJButton softButton2; private Timer alphaChanger; public void createAndShowGUI() { opaqueButton1 = new JButton("Opaque Button"); opaqueButton2 = new JButton("Opaque Button"); softButton1 = new SoftJButton("Transparent Button"); softButton2 = new SoftJButton("Transparent Button"); opaqueButton1.setBackground(Color.GREEN); softButton1.setBackground(Color.GREEN); panel = new JPanel(); panel.setLayout(new java.awt.GridLayout(2, 2, 10, 10)); panel.add(opaqueButton1); panel.add(softButton1); panel.add(opaqueButton2); panel.add(softButton2); panel.setBorder(new EmptyBorder(10, 10, 10, 10)); frame = new JFrame(); frame.add(panel); frame.setLocation(150, 100); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); alphaChanger = new Timer(50, new ActionListener() { private float incrementer = -.03f; @Override public void actionPerformed(ActionEvent e) { float newAlpha = softButton1.getAlpha() + incrementer; if (newAlpha < 0) { newAlpha = 0; incrementer = -incrementer; } else if (newAlpha > 1f) { newAlpha = 1f; incrementer = -incrementer; } softButton1.setAlpha(newAlpha); softButton2.setAlpha(newAlpha); } }); alphaChanger.start(); Timer uiChanger = new Timer(3500, new ActionListener() { private final LookAndFeelInfo[] laf = UIManager.getInstalledLookAndFeels(); private int index = 1; @Override public void actionPerformed(ActionEvent e) { try { UIManager.setLookAndFeel(laf[index].getClassName()); if (laf[index].getClassName().equals("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel")) { UIManager.getLookAndFeelDefaults().put("Panel.background", Color.orange); SwingUtilities.updateComponentTreeUI(frame); } else { panel.setBackground(Color.yellow); SwingUtilities.updateComponentTreeUI(frame); } opaqueButton1.setText(laf[index].getClassName()); softButton1.setText(laf[index].getClassName()); frame.pack(); } catch (Exception exc) { exc.printStackTrace(); } index = (index + 1) % laf.length; } }); uiChanger.start(); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new ButtonTest().createAndShowGUI(); } }); } private static class SoftJButton extends JButton { private static final JButton lafDeterminer = new JButton(); private static final long serialVersionUID = 1L; private boolean rectangularLAF; private float alpha = 1f; SoftJButton() { this(null, null); } SoftJButton(String text) { this(text, null); } SoftJButton(String text, Icon icon) { super(text, icon); setOpaque(false); setFocusPainted(false); } public float getAlpha() { return alpha; } public void setAlpha(float alpha) { this.alpha = alpha; repaint(); } @Override public void paintComponent(java.awt.Graphics g) { java.awt.Graphics2D g2 = (java.awt.Graphics2D) g; g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha)); if (rectangularLAF && isBackgroundSet()) { Color c = getBackground(); g2.setColor(c); g.fillRect(0, 0, getWidth(), getHeight()); } super.paintComponent(g2); } @Override public void updateUI() { super.updateUI(); lafDeterminer.updateUI(); rectangularLAF = lafDeterminer.isOpaque(); } } } 
  • 但对于JComponent ,可以通过调用UIManager.getLookAndFeel().uninitialize();来更改其ColorFontUIManager.getLookAndFeel().uninitialize(); ,但这不适用于containers

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

 import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Random; import javax.swing.JFrame; import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; import javax.swing.Timer; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.UIManager.LookAndFeelInfo; import javax.swing.UnsupportedLookAndFeelException; public class NimbusTestButtonsBackground extends JFrame { private static final long serialVersionUID = 1L; private javax.swing.JButton button; public NimbusTestButtonsBackground() { button = new javax.swing.JButton(); button.setText("Text"); add(button); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); this.pack(); Timer t = new Timer(1000, new ActionListener() { private Random r = new Random(); @Override public void actionPerformed(ActionEvent e) { Color c = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256)); try { LookAndFeel lnf = UIManager.getLookAndFeel().getClass().newInstance(); UIDefaults uiDefaults = lnf.getDefaults(); uiDefaults.put("nimbusBase", c); UIManager.getLookAndFeel().uninitialize(); UIManager.setLookAndFeel(lnf); } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } UIDefaults defaults = UIManager.getDefaults(); defaults.put("Button.background", c); SwingUtilities.updateComponentTreeUI(button); } }); t.start(); } public static void main(String args[]) { try { for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { UIManager.setLookAndFeel(info.getClassName()); break; } } } catch (Exception e) { return; } java.awt.EventQueue.invokeLater(new Runnable() { @Override public void run() { new NimbusTestButtonsBackground().setVisible(true); } }); } } 
  • 然后我看到(这种方式最舒适,最简单等等)覆盖paintComponent是最好的方式

在此处输入图像描述在此处输入图像描述在此处输入图像描述

 import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Container; import java.awt.EventQueue; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridLayout; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.util.Random; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.RepaintManager; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UIManager.LookAndFeelInfo; public class ChangePanelBackgroundNimbus { private JFrame frame = new JFrame(); public ChangePanelBackgroundNimbus() { GradientPane pane = new GradientPane(); pane.setLayout(new GridLayout(6, 4, 10, 10)); for (int i = 1; i <= 24; i++) { pane.add(createButton(i)); } pane.setOpaque(false); frame.add(pane); RepaintManager.setCurrentManager(new RepaintManager() { @Override public void addDirtyRegion(JComponent c, int x, int y, int w, int h) { Container con = c.getParent(); while (con instanceof JComponent) { if (!con.isVisible()) { return; } if (con instanceof GradientPane) { c = (JComponent) con; x = 0; y = 0; w = con.getWidth(); h = con.getHeight(); } con = con.getParent(); } super.addDirtyRegion(c, x, y, w, h); } }); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationByPlatform(true); //frame.setSize(400, 300); frame.pack(); frame.setVisible(true); } private JButton createButton(final int text) { JButton button = new JButton(Integer.toString(text)); return button; } class GradientPane extends JPanel { private static final long serialVersionUID = 1L; private final int h = 150; private BufferedImage img = null; private BufferedImage shadow = new BufferedImage(1, h, BufferedImage.TYPE_INT_ARGB); public GradientPane() { paintBackGround(new Color(150, 250, 150)); Timer t = new Timer(500, new ActionListener() { private Random r = new Random(); @Override public void actionPerformed(ActionEvent e) { paintBackGround(new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256))); } }); t.start(); } public void paintBackGround(Color g) { Graphics2D g2 = shadow.createGraphics(); g2.setPaint(g); g2.fillRect(0, 0, 1, h); g2.setComposite(AlphaComposite.DstIn); g2.setPaint(new GradientPaint(0, 0, new Color(0, 0, 0, 0f), 0, h, new Color(0.4f, 0.8f, 0.8f, 0.5f))); g2.fillRect(0, 0, 1, h); g2.dispose(); } @Override public void paintComponent(Graphics g) { if (img == null || img.getWidth() != getWidth() || img.getHeight() != getHeight()) { img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); } Graphics2D g2 = img.createGraphics(); super.paintComponent(g2); Rectangle bounds = this.getVisibleRect(); g2.scale(bounds.getWidth(), -1); g2.drawImage(shadow, bounds.x, -bounds.y - h, null); g2.scale(1, -1); g2.drawImage(shadow, bounds.x, bounds.y + bounds.height - h, null); g2.dispose(); g.drawImage(img, 0, 0, null); repaint(); } } public static void main(String[] args) { try { for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { UIManager.setLookAndFeel(info.getClassName()); break; } } } catch (Exception e) { e.printStackTrace(); } EventQueue.invokeLater(new Runnable() { @Override public void run() { ChangePanelBackgroundNimbus ml = new ChangePanelBackgroundNimbus(); } }); } }