Java tip: How to use SystemColors to access OS user interface theme colors

Technologies: Java 5+

User interface themes for Mac OS X, Windows, and Linux define the OS-wide look of window frames, buttons, scrollbars, and the like. Preference settings enable users to tune color schemes to taste. For Java applications, changing the theme also sets colors for pre-defined java.awt.SystemColor objects that indicate the color of buttons, text, and more. In principal, applications may use these colors to customize their user interfaces to match the current theme. In practice, there are quite a few problems with doing this.

This article begins a series that discusses Java's SystemColors and their use and problems on different OSes. Series articles also provide color swatches, RGB/HSV values, and downloadable color lists for SystemColors for each of the standard themes on the Mac, Windows, and Linux. The color swatches provide a resource for comparing theme colors and creating custom Java components that match the themes.

Using Java's SystemColors

Java's java.awt.SystemColor subclasses java.awt.Color to hold an RGB color for painting lines, areas, and text. There are no public constructors, but static SystemColor objects are defined for standard OS theme parts:

SystemColor Scope Use
activeCaption background active (front) window title bar
activeCaptionBorder border active (front) window title bar
activeCaptionText text active (front) window title bar
control background component
controlDkShadow border component bevel
controlHighlight border component bevel
controlLtHighlight border component bevel
controlShadow border component bevel
controlText text component
desktop background internal frame
inactiveCaption background inactive (back) window title bar
inactiveCaptionBorder border inactive (back) window title bar
inactiveCaptionText text inactive (back) window title bar
info background tooltip
infoText text tooltip
menu background menu
menuText text menu
scrollbar background scrollbar
text background unselected text field
textHighlight background selected text field
textHighlightText text selected text field
textInactiveText text disabled text field or label
textText text unselected text field
window background window, frame, & panel
windowBorder border window & frame
windowText text window text

For instance, here are the SystemColors for Windows 7's Aero theme:

Windows 7 Aero theme
Name Hex triplet Red Green Blue Hue Satur. Value
activeCaption #99b4d1 153 180 209 211 26 81
activeCaptionBorder #b4b4b4 180 180 180 0 0 70
activeCaptionText #000000 0 0 0 0 0 0
control #f0f0f0 240 240 240 0 0 94
controlDkShadow #696969 105 105 105 0 0 41
controlHighlight #e3e3e3 227 227 227 0 0 89
controlLtHighlight #ffffff 255 255 255 0 0 100
controlShadow #a0a0a0 160 160 160 0 0 62
controlText #000000 0 0 0 0 0 0
desktop #000000 0 0 0 0 0 0
inactiveCaption #bfcddb 191 205 219 210 12 85
inactiveCaptionBorder #f4f7fc 244 247 252 217 3 98
inactiveCaptionText #434e54 67 78 84 201 20 32
info #ffffe1 255 255 225 59 11 100
infoText #000000 0 0 0 0 0 0
menu #f0f0f0 240 240 240 0 0 94
menuText #000000 0 0 0 0 0 0
scrollbar #c8c8c8 200 200 200 0 0 78
text #ffffff 255 255 255 0 0 100
textHighlight #3399ff 51 153 255 210 80 100
textHighlightText #ffffff 255 255 255 0 0 100
textInactiveText #6d6d6d 109 109 109 0 0 42
textText #000000 0 0 0 0 0 0
window #ffffff 255 255 255 0 0 100
windowBorder #646464 100 100 100 0 0 39
windowText #000000 0 0 0 0 0 0

A SystemColor may be used anywhere a Color object can. For example, you can use SystemColors to set a component's foreground and background colors:

JLabel myLabel = new JLabel( "This is a label" );
myLabel.setForeground( SystemColor.infoText );
myLabel.setBackground( SystemColor.info );

You can use a SystemColor within a paint method to draw a gradient:

protected void paintComponent( Graphics g )
{
	GradientPaint gp = new GradientPaint(
		0, 0, SystemColor.controlHighlight,
		0, getHeight( ), SystemColor.controlShadow );
	Graphics2D g2d = (Graphics2D)g;
	g2d.setPaint( gp );
	g2d.fillRect( 0, 0, getWidth( ), getHeight( ) );
}

You can get the red, green, and blue components of a SystemColor:

int red   = SystemColor.textHighlight.getRed( );
int green = SystemColor.textHighlight.getGreen( );
int blue  = SystemColor.textHightlight.getBlue( );

And you can compute new colors that are brighter, darker, etc.:

Color brighterControl = SystemColor.control.brighter( );
Color darkerControl   = SystemColor.control.darker( );

SystemColors vs. Colors

SystemColor objects are identical to Color objects except for one key attribute...

Color objects are immutable.

SystemColor objects are not.

Once defined, a Color object never changes its red/green/blue value. But SystemColors can change. Their red/green/blue values are tied to the underlying OS theme. If the user changes their OS theme's text highlight color, for instance, then SystemColor.textHighlight changes along with it. On the next redraw, any Java component that uses that SystemColor object redraws with the user's updated color.

This feature of SystemColors allows Java applications to draw user interfaces with color schemes that track the user's own OS color scheme preferences. In most cases, no special application coding is needed.

SystemColors vs. UIDefaults

The current application look and feel is managed by Swing's UIManager and characterized by a hash table of UIDefaults that includes theme colors, fonts, and other look and feel attributes. Those UIDefaults often include generic theme colors named the same as the standard SystemColors, such as "textHighlight" for the selected text color.

UIDefaults and SystemColors both provide theme colors for user interface components, but they differ in one key way...

UIDefaults describe an application look and feel.

SystemColors describe the OS look and feel.

If your application uses the native OS look and feel, then the SystemColors and UIDefaults should match. But if you use a non-native look and feel, such as "Nimbus", "Metal", or "CDE/Motif", then the UIDefaults for that look and feel won't match the OS's theme colors in the SystemColor objects.

You can use this difference to your advantage. For instance, you can use the "Metal" look and feel, if you prefer it, but set a text field's selected text color to the OS's highlight color to help your application feel more native, without going all the way to the native look and feel:

JTextField myTextField = new JTextField( );
myTextField.setSelectionColor( SystemColor.textHighlight );
myTextField.setSelectionTextColor( SystemColor.textHighlightText );

For some look and feels, you can set the UIDefaults directly to override a color throughout the look and feel:

UIDefaults myDefaults = UIManager.getDefaults( );
myDefaults.put( "textHighlight", SystemColor.textHighlight );
myDefaults.put( "textHighlightText", SystemColor.textHighlightText );

However, be careful whenever mixing the color scheme of the OS with that of a look and feel. The results may clash or offer poor contrast. The color set for an OS theme or a look and feel are designed to work together, so overriding just a few colors may produce a mess.

Dealing with SystemColors problems

While the SystemColor concept is interesting, it's design is flawed. The class was defined in the early days of OS themes when X11's Motif and Windows 95/98 were the norm. Those themes used simple window frames, beveled buttons, and a limited color set that worked with 256-color graphics cards of the day. But today's OS themes have translucent window frames, gradients and textures, drop shadows, glassy buttons, and full color imagery. Java's SystemColor class hasn't been updated to handle this and its age is showing.

Missing theme colors

There are notable theme parts missing:

  • There are no inactiveControl text and background colors for disabled components.
  • There is no controlTextHighlight color for a highlighted (default) button.
  • There are no menuHighlight background and text colors for highlighting the selected menu item.
  • There is no focus color for halos and outlines to indicate the component with the keyboard focus.
  • There is no support for multi-colored items, such as gradient buttons and window title bars.
  • There are no colors for checks in checkboxes or dots in radio buttons.
  • There is no scrollbar track color.
  • There are no tab colors.
  • There are no progress bar colors.
  • There are no slider colors.
  • There are no cursor colors.

Archaic SystemColors

Some of the SystemColors have little or no meaning with today's OS themes:

  • SystemColor.activeCaption and SystemColor.inactiveCaption originally indicated the title bar color for front and back windows. But most themes today use fancy color gradients, translucency, and shiny glass effects. For these themes, the SystemColors are often left at defaults that rarely match the fancy title bar styles in use.
  • SystemColor.windowBorder, SystemColor.activeCaptionBorder, and SystemColor.inactiveCaptionBorder originally indicated the color of front and back window side and bottom borders. But the Mac's theme has no window borders, the Windows XP theme sets the border to match the title bar color, the Windows Vista/7 Aero theme uses translucent window borders, and many Linux Gnome and KDE themes use complex window borders built from images. The border SystemColors for these themes rarely match the colors actually in use.
  • SystemColor.desktop originally indicated the solid color screen background. But today most users add a favorite wallpaper image to their desktop. SystemColor.desktop is unlikely to have anything to do with that image's colors.
  • SystemColor.control, SystemColor.controlHighlight, SystemColor.controlLtHighlight, SystemColor.controlShadow, and SystemColor.controlDkShadow were originally intended for beveled buttons with a solid background and light and dark edges. But most OS themes today uses gradient buttons, soft rounded edges, shiny glass colors, or animated glowing effects. None of this can be adequately represented with a set of bevel colors, and none of the OS themes try. These bevel SystemColors rarely match the actual look of buttons in the OS theme.

Ambiguous SystemColors

Some of the SystemColors are ill defined or are treated differently on different OSes:

  • SystemColor.menu defines the background color for menus. But is a menu bar a menu? For some OS themes, the menu bar uses the menu background color. For other themes it does not. Java applications trying to mimic this behavior have no way of knowing whether they should or should not use SystemColor.menu for menu bars.
  • SystemColor.controlHighlight was intended as the bright edge of beveled buttons. But the Mac OS X theme instead sets it to the blue halo color used to indicate a component with the keyboard focus. The Windows themes don't do this, which leaves Java applications with no consistent way of getting the focus halo color. Or the bevel bright edge color.
  • SystemColor.window was intended to give the window background color. But most application windows have tool bars, status bars, side bars, and arrays of buttons, check boxes, radio buttons, and combo boxes throughout. Today's OS themes and Java look and feels use SystemColor.control for their default background, instead of SystemColor.window. It isn't clear any more what SystemColor.window is for.

Useful SystemColors

Only a few of the SystemColors are actually useful:

  • SystemColor.text and SystemColor.textHighlight reliably give the unselected and selected text background color for OS themes.
  • SystemColor.textText, SystemColor.textInactiveText, and SystemColor.textHighlightText reliably give the unselected and selected foreground color for OS themes.

None of the other SystemColors are of much cross-platform use.

Workarounds

Swing's UIManager and its look and feel UIDefaults provide a much richer set of theme values. Those values describe a look and feel, and not the OS theme. But if the look and feel is the native look and feel, then the colors generally do match the OS theme.

If you're using the native look and feel, you can get its UIDefaults and query them instead of using a SystemColor:

Color textHighlight = UIManager.getColor( "textHighlight" );

If you're not using the native look and feel, you'll have to initialize that look and feel first, get and save its UIDefaults, then switch to the look and feel you actually want to use. Later you can query the saved native UIDefaults to get OS theme colors.

// Get the native look and feel's defaults.
UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName( ) );
UIDefaults nativeDefaults = UIManager.getDefaults( );

// Switch to the look and feel you want.
UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName( ) );

// Use the native default.
Color textField = nativeDefaults.getColor( "textHighlight" );

Comparing SystemColors for different OSes and their themes

If you're going to use SystemColors, it's useful to see what they look like for different themes on different OSes. What patterns emerge, or don't emerge? For instance:

  • Is text always dark on a light background?
    • No. Some high contrast themes in Linux and Windows use light on dark instead, like this one from Windows 7:
      Windows 7 High Contrast 1 theme
  • Is text always high contrast?
    • No. Some of the old colored themes in Windows XP had low contrast, like this one:
      Windows XP Rainy Day theme
  • Is the text highlight color always a bright color?
    • No. The old Windows XP Silver theme used a gray highlight color that was hard to distinguish from all the other grays in the theme:
      Windows XP silver theme
  • Is the inactive text color always different or toned down compared to the normal text color?
    • No. One high contrast theme in Windows makes the inactive and normal text colors the same. Another high contrast them makes the inactive text color bright green, while all of the other theme colors are black or white. This makes the inactive text brighter and more easily seen than the normal text (which is odd).
      Windows 7 High Contrast White theme
  • Is the control highlight color always brighter than the main control color?
    • No. Even though the color was intended to be for a bright edge on a bevel, all of the classic Windows themes set it to the same color as the control's body.
      Windows 7 Classic theme

The remaining articles in this series review the SystemColors for each of the major OSes and their standard themes.

SystemColors for Mac OS X

Apple's Mac OS X was first released in 1999 and has had nearly the same theme ever since. Known for its glassy buttons, the Mac OS X theme comes in just two colors: Blue and Graphite. While window backgrounds have changed from white stripes in early Mac OS X, to brushed aluminum, then gray gradients, none of these theme styles are user controllable. Mac OS X only allows the user to change the text highlight color.

The longevity of the Mac OS X theme, and the lack of user theme controls, makes the platform a stable target for application developers. Application color schemes can be chosen with high confidence that they won't clash with the OS theme or user customizations.

This color catalog for the Mac OS X theme shows the colors visible to Java applications:

SystemColors for Mac OS X user interface themes

SystemColors for Windows

New themes are introduced in nearly every Microsoft Windows release. Windows 98 added gradient title bars, Windows XP added shaded title bars and buttons, and Vista added translucent title bars and glossy buttons. Each release also includes themes from prior releases. The "classic" beveled buttons of 95 and 98, for instance, are still available in Windows 7, 15 years later. Windows also offers a lot of user control over theme color schemes to tune the look to user taste, or the lack of it.

The wide range of themes and color schemes for Windows make it a difficult target for application developers. If you use the beveled look of Windows 95/98, your application looks horribly dated in XP, Vista, and 7. If you use the bright blues of XP as an application accent color, your application looks childish amongst the subtler color choices of Vista and 7. And if the user has tweaked the theme colors themselves, automatically selecting compatible application colors is challenging.

These color catalogs for Windows themes provide perspective on the standard color scheme choices over the years and how they are visible to Java applications:

SystemColors for Windows XP user interface themes

SystemColors for Windows Vista user interface themes

SystemColors for Windows 7 user interface themes

SystemColors for Linux

Linux distributions tend towards one of two OS user interfaces: Gnome or KDE. Each has its own style for window frames, buttons, scrollbars, and the like. Distributions further differentiate themselves by offering different default themes, such as the distinctive orange of Ubuntu or the light blue of Fedora. In any case, Linux control panels offer user control over the color scheme and Linux web sites offer loads of downloadable themes for Gnome and KDE.

The breadth of theme choices for Gnome and KDE make Linux a difficult platform for application developers. Further complicating things, none of the Java virtual machines to date properly forward theme color choices to Java applications as SystemColors. Instead, the SystemColors are left at defaults that have nothing to do with the OS theme.

These color catalogs for Linux show provide the SystemColor defaults for Java applications:

SystemColors for Linux Gnome user interface themes

SystemColors for Linux KDE user interface themes

SystemColors for FreeBSD

FreeBSD distributions tend to use the KDE user interface found on Linux, but Gnome is also available. In most cases, Linux applications can run unmodified on FreeBSD. While there is a FreeBSD-specific Java distribution, it's based upon recompilation of the standard OpenJDK and based upon Gnome's GTK+ user interface toolkit. This gives FreeBSD the same Java issues as those found on Linux with Gnome or KDE:

SystemColors for Linux Gnome user interface themes

SystemColors for Linux KDE user interface themes

SystemColors for Solaris

Oracle's Solaris uses the Gnome user interface common on Linux and Solaris Java distributions are based upon Gnome's GTK+ user interface toolkit. So, Solaris has the same Java issues as those found on Linux with Gnome:

SystemColors for Linux Gnome user interface themes

SystemColors for Android

Google's Android is an OS for mobile devices, such as smart phones and tablets. The OS is based upon a Linux kernel with a Java-based user interface running in a custom virtual machine. Google's version of Java is not compatible with standard Java and does not support the java.awt class library that contains the SystemColor class.

SystemColors for ChromeOS

Google's ChromeOS is based upon Linux, but locked to run a custom web browser-based user interface centered on Google's Chrome browser. While Java support is planned, it is not available in the current releases.

SystemColors for iOS

Apple's iOS is a Mac OS X derivative used for iPhones, iPods, and iPads. Apple's rules governing the platform restrict code development to C, C++, or Objective-C. Java is not supported.

SystemColors for QNX

RIM's QNX is an embedded system OS being extended to mobile devices, such as smart phones and tablets. The OS currently has no Java support.

SystemColors for Symbian

Nokia's Symbian is an OS used on smart phones. Applications can be developed using Oracle's Java ME (Micro Edition) — a light-weight Java intended for mobile devices. Java ME drops the desktop-oriented java.awt and java.Swing toolkits and replaces them with LWUIT (Light Weight User Interface Toolkit). This new toolkit doesn't include AWT's SystemColor class.

SystemColors for WebOS

HP's WebOS is a mobile OS originally developed by Palm and aimed at mobile devices, such as smart phones and tablets. The OS is based upon a Linux kernel with a custom user interface and C/C++ software development kit. While a Java virtual machine was included in early releases of WebOS, that JVM has since been discontinued and Java is no longer supported.

Further reading

Related articles at NadeauSoftware.com

Web articles

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.

More information about formatting options

Nadeau software consulting
Nadeau software consulting