2

While using the Nimbus L&F feel in Java, I am having problems with changing the background color for a JButton more than once. In the code below, I have a simple Swing application that displays a JButton and attempts to change the color once per second. However, only the first color is being applied. Can anyone provide any suggestions on how to make this change more than once? I'm running java 6.29.

public class NimbusTest3 extends JFrame {
    private javax.swing.JButton button;

    public NimbusTest3(){
        button = new javax.swing.JButton();
        button.setText("Text");
        this.add(button, BorderLayout.CENTER);
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        this.pack();

        Timer t = new Timer(1000, new ActionListener() {
            Random r = new Random();
            @Override
            public void actionPerformed(ActionEvent e) {
                UIDefaults buttonDefaults = UIManager.getLookAndFeelDefaults();
                Color c = new Color(r.nextInt(
                        256), r.nextInt(256), r.nextInt(256));
                System.out.println(c);
                buttonDefaults.put("Button.background", c);
                button.putClientProperty("Nimbus.Overrides", buttonDefaults);
                button.putClientProperty("Nimbus.Overrides.InheritDefaults", false);
                SwingUtilities.updateComponentTreeUI(button);
                button.repaint();
            }
        });
        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 NimbusTest3().setVisible(true);
            }
        });
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Gregory Peck
  • 636
  • 7
  • 22

2 Answers2

4

EDIT :

I agreed not possible to change that direct way (maybe there is another dirty hacks) is possible that with very complicated way (development of Nimbus L&F ended somewhere on first half), another (similair) issue is in my question about Font

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 NimbusTest3 extends JFrame {

    private static final long serialVersionUID = 1L;
    private javax.swing.JButton button;

    public NimbusTest3() {
        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 NimbusTest3().setVisible(true);
            }
        });
    }
}
Community
  • 1
  • 1
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • @mKorbel updateComponentTreeUI is already called, so it does not solve his issue. But there is not much point in using L&F if OP has to use dedicated client properties on all his components. Then 'Rob I' solution is actually a lot simpler and more efficient. – Guillaume Polet May 21 '12 at 14:23
  • did you to check Nimbus Default for JButton – mKorbel May 21 '12 at 14:24
  • @mKorbel Thanks for the links, but they don't seem to solve the problem of setting the value more than once. – Gregory Peck May 21 '12 at 14:50
  • @Gregory Peck see my edit there, I searching in the dirty tunels for an alternative(s), ??? maybe exist???? but for first version, for un_official Nimbus L&F – mKorbel May 21 '12 at 15:58
  • @mKorbel Thanks, this works! It changes only the color of the JButton it is applied to and it leaves the rest of the UI the same. Also, what do you mean by your comment "unofficial Nimbus L&F"? – Gregory Peck May 21 '12 at 16:11
  • before its added to the Swing packages, I'd suggest to use another [custom Look and Feel](http://stackoverflow.com/a/3954646/714968) that bases on Swing APIs, not to use some (since is great and with todays performance) L&F that looks like is very buggy and developlment never ended – mKorbel May 21 '12 at 16:14
  • I understand now - unfortunately I'm stuck w/ the Java release and L&F - its not under my control to change them. Hopefully we'll move to Java 7 in the not too distant future. – Gregory Peck May 21 '12 at 16:36
1

You need to add this line:

button.setBackground(c);

to your code. None of the other code - buttonDefaults, putClientProperty, updateComponentTreeUI, repaint is necessary.

Rob I
  • 5,627
  • 2
  • 21
  • 28
  • Thanks Rob as this does set the color. Nimbus will even add the appropriate highlights/shading to the button when set this way. While this is the solution I will use in my application, I'll leave the question open for a while to see if someone can answer it using the Nimbus properties. – Gregory Peck May 21 '12 at 14:57