Until the 1.4.2 release, J2SE included three pluggable look-and-feel (PLAF) designs:
- Windows: Emulates the Windows 2000 operating system (because of licensing restrictions, this PLAF can only be used under a Windows platform)
- Motif: Emulates a Motif application
- Metal: Uses its own look and feel independent from any existing operating system
J2SE 1.4.2 provides two additional look-and-feel designs, which John Zukowski described in his Magic with Merlin column "J2SE 1.4.2 gets two new look-and-feel designs" (see Resources). The two new look-and-feel designs are:
- Windows XP: Emulates the Windows XP operating system (it can only be used under a Windows platform)
- GTK+: Emulates a GTK application under Linux
It's better to look good than to feel good
For most people, an application's look and feel is only a matter of preferences and aesthetics. But in some cases it is necessary to customize the application's look and feel so that it uses specific fonts, color schemes, or icons. Visually impaired users, for example, often need a look and feel with a high contrast between text and background, as well as large fonts and icons. The "IBM Java Accessibility Checklist" (see Resources) specifies that all user interface objects in an application must support high contrast settings.
Earlier releases of the Java platform did not support color and font preferences very well. Since J2SE 1.4 -- and especially with the introduction of the new Windows XP and GTK look-and-feel designs in J2SE 1.4.2 -- users can now configure the desired look-and-feel designs. The Windows look and feel tries to reuse the color and font schemes of the underlying Windows platform, and the GTK look and feel enables Linux users to define some scripts to customize the look and feel.
At first glance, the improvement of the "native" look-and-feel designs seems to make the Metal look and feel useless. However, there are still some cases where the Metal look and feel (or a customized version of it) can be helpful. For instance:
- If you need a look and feel that runs under any platform and is customizable even when used by an unsigned applet
- If you need more customization than the possibilities offered by the other look-and-feel designs
- If you are using an earlier release of the Java platform for which the latest improvements are not available
This article explains how you can modify the Metal look and feel to use specific font and color schemes. You'll also learn how to modify the icons used to draw widgets such as check boxes, radio buttons, trees, and file dialogs.
I'll begin by explaining how the colors and the fonts used by the look and feel can be overloaded. Then we'll review how the icons used by the standard widgets can be modified. Finally, we'll walk through a complete example of a new look and feel where you can define the settings for the colors, fonts, and icon sizes in a simple text file. You can then use our example to create your own high-contrast look and feel.
Overloading the Metal look and feel -- modifying the colors and the fonts
The javax.swing.plaf.metal.MetalLookAndFeel class is the main class of the Metal look and feel. The Java API documentation of this class (see Resources) shows that most of the methods defined in it are getters returning the colors and fonts to draw the different widgets available in the Swing framework. However, the return value of these getters is not directly implemented in this class but is delegated to another class, which is called a theme. The only purpose of the theme is to provide the values of the colors and fonts to use.
The Metal look and feel uses a pluggable theme architecture. The look and feel itself (javax.swing.plaf.metal.MetalLookAndFeel) defines what the widgets look like and how they should react to user interactions, while the theme defines which colors and fonts you should use when painting the widget. You can define a new theme by creating a new class that inherits from javax.swing.plaf.metal.MetalTheme.
Figures 1 and 2 show two screenshots from the SwingSet demos that come with the JSDK. They demonstrate how different themes can change the look of an application, even when the same look and feel is used.
Figure 1. Default theme

Figure 2. High Contrast theme

Thus, customizing the colors and the fonts of the Metal look and feel is as easy as:
- Creating a new class that extends
javax.swing.plaf.metal.MetalThemeor its default implementationjavax.swing.plaf.metal.DefaultMetalTheme(see the reference to the Java API documentation in the Resources section) - Overloading the
getXXXFont()orgetXXXColor()methods from the theme class so they return the fonts or colors needed in the new theme. - Setting the new theme in the Metal look and feel by invoking the
MetalLookAndFeel.setCurrentTheme(theme)static method.
The Java API documentation (see Resources) for javax.swing.plaf.metal.MetalTheme shows that you can overload about 50 different methods to define, on a fine-grained level, which colors and fonts have to be used. Unfortunately, most of these methods are not documented, making it a painful task to test each method to check the impact it has on the user interface.
Fortunately, you usually don't need to overload all of the available methods to get an acceptable result -- if javax.swing.plaf.metal.MetalTheme provides numerous methods, its default implementation javax.swing.plaf.metal.DefaultMetalTheme implements most of them in a consistent way so that they all return the result of one of the following methods:
getBlack()getWhite()getPrimary1()getPrimary2()getPrimary3()getSecondary1()getSecondary2()getSecondary3()getControlTextFont()getMenuTextFont()getSubTextFont()getSystemTextFont()getUserTextFont()getWindowTitleFont()
Thus, subclassing javax.swing.plaf.metal.DefaultMetalTheme and overloading these eight colors and six fonts is usually sufficient to get a consistent new theme.
Instead of hardcoding these methods (as is done in the themes provided by the Java platform), it's a good idea to implement a generic theme that returns colors and fonts specified in an external resource file. This way, we can easily define a new theme -- we only need to edit a few values with any text editor.
In some cases, it may be necessary to modify the icons and graphical resources used by the look and feel as well. For example, you may want to modify the icons used by the check boxes and radio buttons to paint their status, or you may want to use other icons to paint the folders and nodes of a tree component.
Modifying the icons, for example, is necessary if you want a look and feel with large fonts. The size of the icons used in check boxes and radio buttons should be adapted to the size of their font. Check boxes with large fonts won't help a visually impaired user if he can't tell whether the check box is checked or unchecked, because the size of its icon has remained unchanged.
Figure 3 shows an example of a high contrast and large font theme in which the size of the icons are unchanged. You can see the disproportion between the font size and the size of the icons.
Figure 3. A high contrast and large font theme without adjusted icon size

Unfortunately, icons cannot be modified in a theme. Therefore, we have to use another technique if we want to overload the icons used by the Metal look and feel.
The Metal look and feel stores the list of the graphical resources to be used (colors, fonts, and images) in a javax.swing.UIDefaults object, which is basically a kind of hashtable. Each image required by the different
widgets is stored by the look and feel under a specific key in this table, so that it can be easily retrieved. That means also that if you know under which key a specific image is stored, you can replace it by storing another image under the same key.
Let's look at how the Metal look and feel initializes the table containing the graphical resources.
When the look and feel is created, it first instantiates an empty UIDefaults object that is filled by the following methods:
initClassDefaults(UIDefaults)initComponentDefaults(UIDefaults)initSystemColorDefaults(UIDefaults)
Each of these methods is consecutively invoked by the look and feel itself. They consecutively store graphical resources (either colors, fonts, or images) in the UIDefaults tables under unique keys.
For more detail, see the API documentation (see Resources) of the javax.swing.plaf.MetalLookAndFeel class. The initialization of the images is done in initComponentDefaults(UIDefaults). Overloading this method allows you to replace any standard image used in the look and feel.
Unfortunately, the keys under which the icons are stored are not documented, but the source code of the javax.swing.plaf.MetalLookAndFeel class provides this information. It reveals how the icons are built for the Metal
look and feel. Table 1 shows a list of the existing keys that refer to icons in the Metal look and feel:
Table 1. Keys that refer to icons in the Metal look and feel
CheckBox.icon | InternalFrame.closeIcon |
RadioButton.icon | InternalFrame.maximizeIcon |
InternalFrame.icon | InternalFrame.iconifyIcon |
InternalFrame.iconifyIcon | InternalFrame.minimizeIcon |
FileView.directoryIcon | Menu.checkIcon |
FileView.fileIcon | Menu.arrowIcon |
FileView.computerIcon | MenuItem.checkIcon |
FileView.hardDriveIcon | MenuItem.arrowIcon |
FileView.floppyDriveIcon | CheckBoxMenuItem.checkIcon |
FileChooser.detailsViewIcon | CheckBoxMenuItem.arrowIcon |
FileChooser.homeFolderIcon | RadioButtonMenuItem.checkIcon |
FileChooser.listViewIcon | RadioButtonMenuItem.arrowIcon |
FileChooser.newFolderIcon | Tree.openIcon |
FileChooser.upFolderIcon | Tree.closedIcon |
Slider.horizontalThumbIcon | Tree.leafIcon |
Slider.verticalThumbIcon | Tree.expandedIcon |
InternalFrame.icon | Tree.collapsedIcon |
InternalFrame.paletteCloseIcon |
In contrast to the other look-and-feel designs delivered with the Java platform, the Metal look and feel does not use GIF files to paint its icons. It creates them dynamically through a factory class called javax.swing.plaf.metal.MetalIconFactory. For each of the keys listed in Table 1, it provides a corresponding getXXXIcon() method that paints a vectorial icon.
Vectorial icons created by a factory have the advantage that they can use the colors defined by the current theme instead of predefined colors. Because the icons are vectorial, it is usually easy to modify their scale without sacrificing quality. Unfortunately, except for four icons, none of the methods in MetalIconFactory accepts a parameter that defines the size of the icon. Therefore, the only way to define the size of icons is to build a completely new icon factory.
Fortunately, there is a workaround to this problem. You can create a class that implements the javax.swing.Icon interface, takes an existing icon and scale factor as its argument in its constructor, and uses the java.awt.Graphics2D API to paint a rescaled version of the icon as a bitmap image (see Listing 1). Of course, it means a loss of quality when an icon is enlarged. However, this is much easier to implement than building a new icon factory. Furthermore, the quality is still acceptable for simple icons such as check boxes and radio buttons.
Listing 1. An icon magnifier
/** A class to create a magnified version of an existing icon */
protected class MagnifiedIcon implements Icon {
private Icon icon ;
private double factor ;
public MagnifiedIcon(Icon icon, double factor) {
this.icon = icon ;
this.factor = factor ;
}
public int getIconWidth() {
return (int)(icon.getIconWidth()*factor) ;}
public int getIconHeight() {
return (int)(icon.getIconHeight()*factor) ;}
public void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2d = (Graphics2D)g.create() ;
g2d.translate(x,y);
g2d.scale(factor, factor);
icon.paintIcon(c,g2d,0,0);
g2d.dispose();
}
}
|
A customizable, high-contrast look and feel
Listing 2 shows the source code for the generic look and feel that is based on the Metal look and feel and a color scheme that was created to provide a customizable, operating system-independent, high-contrast look and feel. (Download the source code from Resources.)
Lines 9 through 16 load the external resource file that defines the properties of the look and feel. They install a customized theme that uses this resource file to define the colors and the fonts.
Lines 18 through 20 overwrite standard methods of MetalLookAndFeel so that the name, description, and ID of the look and feel is also externalized in the resource file.
Lines 22 through 53 modify the UIDefaults of the look and feel to magnify the standard icons by a factor defined in the external resource file. The magnification itself is made by the MagnifiedIcon inner class (lines 95 through 113).
Lines 56 through 92 comprise the implementation of the customized theme. They first read in the resource file the name and size of the font to be used (lines 64 through 70). Then they overwrite the getter methods of DefaultMetalTheme so that the font and colors defined in the external resource file are used.
Listing 3 shows the external resource files for the Black on White Look and Feel, Large Fonts. The font size for this look and feel is set to 30 (line 5), the icons are scaled to 250 percent of their original size (line 3), and the basic colors are set to black and white (lines 6 through 15).
Listing 3. HighContrastLAF.properties: Black on white
1 name = High Contrast Look And Feel 2. description = Black on white, large fonts 3. iconMagnificationFactor = 2.5 4. fontName = Dialog 5. fontSize = 30 6. backgroundColor = FFFFFF 7. foregroundColor = 000000 8. primaryColor1 = 000000 9. primaryColor2 = FFFFFF 10. primaryColor3 = FFFFFF 11. secondaryColor1 = 000000 12. secondaryColor2 = C0C0C0 13. secondaryColor3 = FFFFFF 14. selectionForeground = FFFFFF 15. selectionBackground = 000000 |
Figure 4 shows a screenshot of this look and feel.
Figure 4. Black text on white background

In the same way, you can create a high-contrast look and feel with white text on black background and normal font size just by providing another resource file as shown in Listing 4.
Listing 4. HighContrastLAF.properties: White on black
1. name = High Contrast Look And Feel 2. description = White on black 3. iconMagnificationFactor = 1 4. fontName = Dialog 5. fontSize = 14 6. backgroundColor = 000000 7. foregroundColor = FFFFFF 8. primaryColor1 = FFFFFF 9. primaryColor2 = 000000 10. primaryColor3 = 000000 11. secondaryColor1 = FFFFFF 12. secondaryColor2 = 808080 13. secondaryColor3 = 000000 14. selectionForeground = 000000 15. selectionBackground = FFFFFF |
Figure 5 shows the result of Listing 4.
Figure 5. White text on black background

Using the new look and feel in your Java application
You can use the newly created look and feel in any Swing application by invoking the following line in the main method before the first widget is created:
UIManager.setLookAndFeel("HighContrastLAF");
|
Ideally, your product provides a dialog or preference page that lets users select the look and feel of their choice. But if you are not ready to invest so much effort, a much easier solution is to use the system properties to allow users to specify the look and feel in the command line that starts the program, as shown in Listing 5.
Listing 5. Initializing the LAF from a system property
String plaf = System.getProperty("plafName") ;
if (plaf!=null) try {
UIManager.setLookAndFeel(plaf);
} catch (Exception e) { ("Error loading PLAF "+plaf+":"+e);}
|
Users can then select a specific look and feel by using the following syntax in the command line when they start the application:
java -DplafName=HighContrastLAF -classpath CLASSPATH MAINCLASS ARGUMENTS |
In this article, we've shown how easy it is to customize the cross-platform Metal look and feel. As we've discussed, this can be achieved by subclassing the MetalLookAndFeel and DefaultMetalThemes classes. We have also shown how you can easily enlarge icons by using scaled icons. You can use the source code from this article as is or modify it in your projects to provide more customization possibilities for visually impaired users.
| Name | Size | Download method |
|---|---|---|
| j-customlaf.zip | 1KB | HTTP |
Information about download methods
- John Zukowski's Magic with Merlin column touched on the two new look-and-feel designs in J2SE 1.4.2 (developerWorks, May 2003).
- See the IBM Java Accessibility Checklist that Java applications should fulfill to comply with section 508 of the U.S. Rehabilitations Act and related accessibility standards.
- Visit the JFC home page to learn about JFC/Swing.
- The JFC home page contains a series of papers related to the creation of pluggable look-and-feel designs.
- This Web site provides a collection of Swing look-and-feel designs.
- See the Java API documentation
for the API of the different classes referenced in this article.
- To learn more about Java accessibility features and creating accessible Java-based software, see the "IBM Guidelines for Writing Accessible Applications Using 100% Pure Java."
- Dr. Barry Feigenbaum, a Senior IT Specialist at the IBM Worldwide Accessibility Center, has written several books and articles related to accessibility, including "Coding for accessibility" (developerWorks, October 2002).
- Find hundreds more Java technology resources on the developerWorks Java technology zone.
Yannick Saillet joined IBM Germany as a software developer in 1998. He first worked for IBM Learning Services as a software engineer in several distributed learning projects. He joined the IBM Boeblingen Laboratory in 2000 where he has been active in the development of the DB2 Intelligent Miner products. You can contact Yannick at ysaillet@de.ibm.com.




