Skinning a Slider with Nimbus
So time for a example of how to skin a Swing JSlider using the Nimbus Look and Feel and some simple painting code. So this is what we get with the standard Nimbus look slider on a dark grey background.

All of the Nimbus skin comes from a set of properties in the UIManager defaults table. The keys we will be changing for this example are:
- “Slider.thumbWidth”
- “Slider.thumbHeight”
- “Slider:SliderThumb.backgroundPainter”
- “Slider:SliderTrack.backgroundPainter”
You can customize the look for a Component either globally for all instances of the component or locally for a single component instance. To change all sliders globally you can set these properties using UIManager.put(key,value) but in this example I will just set them locally for a single slider. To set UI defaults localy for a single component instance you need to create a UIDefaults map, insert you properties and then set it as a client property on the component:
JSlider slider = new JSlider(0, 100, 50);
UIDefaults sliderDefaults = new UIDefaults();
....
sliderDefaults.put(<<key>>,<<value>>)
....
slider.putClientProperty("Nimbus.Overrides",sliderDefaults);
slider.putClientProperty("Nimbus.Overrides.InheritDefaults",false);
The “Nimbus.Overrides.InheritDefaults” key states if the values in “Nimbus.Overrides” should be merged with the defaults(false) or replace them(true). So next some examples for what properties we should set to skin the slider:
sliderDefaults.put("Slider.thumbWidth", 20);
sliderDefaults.put("Slider.thumbHeight", 20);
sliderDefaults.put("Slider:SliderThumb.backgroundPainter", new Painter() {
public void paint(Graphics2D g, JComponent c, int w, int h) {
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setStroke(new BasicStroke(2f));
g.setColor(Color.RED);
g.fillOval(1, 1, w-3, h-3);
g.setColor(Color.WHITE);
g.drawOval(1, 1, w-3, h-3);
}
});
sliderDefaults.put(”Slider:SliderTrack.backgroundPainter”, new Painter() {
public void paint(Graphics2D g, JComponent c, int w, int h) {
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setStroke(new BasicStroke(2f));
g.setColor(Color.GRAY);
g.fillRoundRect(0, 6, w-1, 8, 8, 8);
g.setColor(Color.WHITE);
g.drawRoundRect(0, 6, w-1, 8, 8, 8);
}
});
The lets pop that code into a sample app and run it and see what it looks like.

The original Nimbus slider on the bottom and the skinned one on top, both running in the same application. Here is the source so you can try it your self. Let me know if this was useful and what other examples you would like to see.
SliderSkinDemo.java |
August 20th, 2008 at 9:32 pm
Nice demo–one question: Nimbus is supposed to be vector-based, which I assume means scalable–when using a custom painter what does one need to take care of to make sure scaling is handled correctly? I assume the hard-coded offsets need to be multiplied by some factor available in context? Or am I misunderstanding what you mean by vector-based in the presentations?
Thanks
Patrick
August 21st, 2008 at 12:48 pm
Yes, this is very useful. The various “Overrides” properties and client defaults are not explained well elsewhere, so it is extremely helpful to see concise working examples like this!
I’ve struggled to figure out how to make JButtons smaller, specifically by removing some of the extra internal padding/margins. So I’d be very interested in examples that delve into borders, insets, padding, margins, etc. For instance, I wanted to create a tiny square button next to a date field that brings up a calendar popup.
I also really hope bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6723524 is fixed before the final release, as it can make Nimbus JTables look really awful.
August 21st, 2008 at 2:31 pm
could you provide a demo to show how easily the blue style of nimbus can be changed to another color style, because
that would be really interesting.
I was wondering where I could find a list of synth properties and the Nimbus values for it.
And BTW, good work!
August 21st, 2008 at 4:03 pm
Instead of these hard-coded strings like “”Nimbus.Overrides.InheritDefaults” could you just provide let’s say hardcoded static String constants or even better a nice enum with a toString() implementation for each value?
August 22nd, 2008 at 12:46 pm
Patrik: There is three advantages of Nimbus being vector graphics based: #1 is for when you draw a large button say 200×200 it still looks good, if it was a stretched image it would look poor. #2 When you Nimbus components in a scenegraph like in JavaFX and scale and rotate them they always look crisp. The same if you print them on a high dpi printer. #3 High DPI, this was always a aim of Nimbus though we did not get to finish work on it, hopefully for Java 7. This is the case where the hard coded sizes need to be multiplied by a scaling constant. Once we get this finished we will provide examples of how to write painters that support high DPI.
Eric: I will try and blog an answer to how to change the padding around components like button. Have you tried , it should net be hard, one property to change. Have you tried mini components? http://www.jasperpotts.com/blog/2007/12/nimbus-large-small-mini-components/
The JTable bug I have not had a chance to look at, just scanned it and I think its a known issue that we can fix which is we can not give nimbus styling to Renderers that do not extend the DefaultRenderers. So I am not sure there is a better answer than the workaround you have. I will look into it when I have time in more details but not sure when that will be as I am flat out working on Java FX at the moment.
Tom: I will do a blog on this but basically all you need to do is write a quick prog that lists and prints all the contents of the map from UIManager.getLookAndFeelDefaults().
Jacek: Unfortunately that is something that we could not do at the moment because of politics. Adding that would be a API change which would require JCP approval and could not be done in a update release on a X.0 release.
August 22nd, 2008 at 1:34 pm
>Jacek: Unfortunately that is something that we could not do at the moment because of politics. Adding that would be a API change >which would require JCP approval and could not be done in a update release on a X.0 release.
… but sun could still provide the enums as java files which can be included in our apps. This won’t break the backwards compatibility.
(in worst case put it into the JavaFX package)
It seems like it is possible to introduce a API without the JCP just look into the draggable applet feature. … just write experimental technology above it and do not generate javadocs
August 28th, 2008 at 1:21 am
Jasper Potts,
Nimbus is awesome. I wonder if it is possible to remove the inset spacing for component. For example, after setMargin to all zero to JButton with imageIcon, there still a lot of padding around. Is there a way to remove those space ? Because when one switch from the metal L&F to Nimbus, suddenly images are truncated due to the space.
September 18th, 2008 at 2:25 pm
hello, is it possible to use nimbus on the mac?
is it allowed to fetch the new swing classes that contain nimbus and deploy them with your application so that they can also run on the mac?
September 18th, 2008 at 2:59 pm
i just tried the SliderSkinDemo.java which is attached to this blogpost in java6u10 rc2 but the skinning does not seem to work. the two sliders look exactly the same.
September 27th, 2008 at 2:35 pm
Yeah, skinning this way does not work in java6u10 rc2 (build 32). It works only if you do laf.getDefaults().put, but then you skin ALL components and not just a specific component.
November 13th, 2008 at 10:16 pm
While it’s true that this particular piece of code does not skin the component in the released version of java6u10, it definitely works, you can skin an individual component. The part that (now) seems to be missing here is the state.
Change “Slider:SliderThumb.backgroundPainter” into “Slider:SliderThumb[Focused].backgroundPainter” and ”Slider:SliderTrack.backgroundPainter” into “Slider:SliderTrack[Enabled].backgroundPainter” et voilà.
I don’t know if it’s possible to specify more than one state in a single client property, i didn’t find how.
Jasper, btw do you have any update on when/if we’ll be able to either test the nimbus designer tool and/or have it opensourced ?