【问题标题】:Update LookAndFeel Values On The Fly即时更新 LookAndFeel 值
【发布时间】:2013-01-21 06:02:48
【问题描述】:

我希望能够即时更新我的​​ 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)

显然,有些东西是空的,但我不知道它是什么或如何解决它。一定有什么我不明白的。我查看了有关 setting background colors in Nimbusoverriding the LookAndFeel information after startup 的其他 StackOverflow 问题。

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

【问题讨论】:

    标签: java swing jpanel look-and-feel nimbus


    【解决方案1】:
    • Java6 的所有代码,必须更改 Java7 的 Nimbus 导入

    • Nimbus 有一些惊喜,其中之一是可以(没有肮脏的黑客,我要为那些黑客留下 cmets)将 Background 更改为 JPanel 一次

    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();
            }
        }
    }
    

    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);
                }
            });
        }
    }
    
    • 然后我认为(这种方式是最舒适、最简单等)覆盖 paintComponentJPanel 是最好的方式

    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();
                }
            });
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-09-03
      • 1970-01-01
      • 2013-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多