Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Enhance the accessibility of your GUIs

Build a customizable cross-platform look and feel for visually impaired users

Yannick Saillet (ysaillet@de.ibm.com), Software Engineer, IBM, Software Group
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.

Summary:  One of the main characteristics of the JFC/Swing framework is its ability to use pluggable look-and-feel designs. The same application can be run with different look-and-feel designs without requiring any modification. In this article, Software Engineer Yannick Saillet explains the mechanism behind the Metal look and feel -- one of the standard look and feel designs provided with the J2SE platform -- and demonstrates how to modify it into a universal, customizable look and feel to accommodate special user needs, such as high contrast or large fonts for the visually impaired.

Date:  09 Jul 2003
Level:  Introductory

Activity:  11195 views
Comments:  

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
Default theme

Figure 2. High Contrast theme
High Contrast theme

Thus, customizing the colors and the fonts of the Metal look and feel is as easy as:

  1. Creating a new class that extends javax.swing.plaf.metal.MetalTheme or its default implementation javax.swing.plaf.metal.DefaultMetalTheme (see the reference to the Java API documentation in the Resources section)

  2. Overloading the getXXXFont() or getXXXColor() methods from the theme class so they return the fonts or colors needed in the new theme.

  3. 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.


Modifying the icons

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
A 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.iconInternalFrame.closeIcon
RadioButton.iconInternalFrame.maximizeIcon
InternalFrame.iconInternalFrame.iconifyIcon
InternalFrame.iconifyIconInternalFrame.minimizeIcon
FileView.directoryIconMenu.checkIcon
FileView.fileIconMenu.arrowIcon
FileView.computerIconMenuItem.checkIcon
FileView.hardDriveIconMenuItem.arrowIcon
FileView.floppyDriveIconCheckBoxMenuItem.checkIcon
FileChooser.detailsViewIconCheckBoxMenuItem.arrowIcon
FileChooser.homeFolderIconRadioButtonMenuItem.checkIcon
FileChooser.listViewIconRadioButtonMenuItem.arrowIcon
FileChooser.newFolderIconTree.openIcon
FileChooser.upFolderIconTree.closedIcon
Slider.horizontalThumbIconTree.leafIcon
Slider.verticalThumbIconTree.expandedIcon
InternalFrame.iconTree.collapsedIcon
InternalFrame.paletteCloseIcon

Scaling the icons

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
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
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


Conclusion

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.



Download

NameSizeDownload method
j-customlaf.zip1KB HTTP

Information about download methods


Resources

About the author

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.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology
ArticleID=10837
ArticleTitle=Enhance the accessibility of your GUIs
publish-date=07092003
author1-email=ysaillet@de.ibm.com
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers