Mac Java tip: How to create Aqua recessed borders

Technologies: Java 5+, Mac OS X 10.5+

Grouping together related components helps organize a user interface and make it easier to learn and use. Java provides several border styles for outlining groups, but none of them match the Mac's recessed style. This article shows how to create a recessed border using special UI defaults available to Mac Java applications.

Using standard Java border styles

To outline a group of components, place them all within a JPanel and call setBorder( ) with a new border object:

JPanel group = new JPanel( );
group.setBorder( new EtchedBorder( ) );

javax.swing.border includes several standard border styles:

  • BevelBorder creates a raised or lowered beveled look that went out of GUI style in the 1990s. SoftBevelBorder does the same thing with a slightly softer look. Use these with care (or not at all) or your application will look like it came with Windows 95.
  • EtchedBorder creates an "etched" double line border that is widely used in Windows and Linux applications. LineBorder draws a simpler single line border. Both of these are reasonable fallbacks if you don't want to use the Aqua recessed border discussed below.
  • MatteBorder creates a thick border by tiling an image or drawing with a color. This is pretty ugly and probably should not be used.
  • EmptyBorder creates a border of empty space.

The remaining border classes combine together one or more of the above borders:

  • CompoundBorder combines any two of the above borders. One common use combines an EtchedBorder to outline a group and an EmptyBorder to add padding within the border so that the group's components don't touch the border line.
  • TitledBorder combines one of the above borders and a text title for the group. It is commonly combined with a LineBorder or EtchedBorder to outline a group and name it.

Here's what these look like:

Beveled and soft beveled borders
Figure 1. Java's BevelBorder (top, raised and lowered) and
SoftBevelBorder (bottom, raised and lowered).
Etched and line borders
Figure 2. Java's EtchedBorder (top, raised and lowered) and
LineBorder (bottom).
Matte borders
Figure 3. Java's MatteBorder with a color and a repeating image.
Titled border
Figure 4. Java's TitledBorder with an EtchedBorder.

Creating the Mac's Aqua recessed border style

Swing's look and feel features encapsulate and hide code to draw buttons, check boxes, and other components in different visual styles. For instance, Sun's standard "Metal" look and feel creates a semi-metalic blue appearance for components, while the ancient "Motif" look and feel creates a heavily-beveled style from the 1990s.

On a Mac, the default "Mac OS X" look and feel gives Java applications the Aqua look automatically. It does the right thing for buttons, sliders, and other components, but it won't automatically give you Aqua-style recessed borders. For that you need to do some brief special code.

Using UI defaults to get Aqua borders

Like all look and feels, "Mac OS X" provides a hash table of UI defaults that are used to initialize colors, fonts, icons, borders, and margins for new Swing components. The available defaults differ from one look and feel to another. Apple's "Mac OS X" look and feel includes a few special defaults that enable hidden features not available through the standard Swing API. (See All UI defaults names for common Java look and feels on Windows, Mac OS X, and Linux.)

That "Mac OS X" look and feel defines these two special UI defaults keys:

  • "InsetBorder.aquaVariant"
  • "TitledBorder.aquaVariant"

The value for both of these is a Border object. To get these values, call getBorder( ) on the look and feel's UIDefaults hash table from the UIManager:

Border aquaBorder = UIManager.getBorder( "InsetBorder.aquaVariant" );

And to use the border, simply call setBorder( ) on a JPanel in the usual way:

JPanel group = new JPanel( );
group.setBorder( aquaBorder );
Aqua borders
Figure 5. Apple's inset (left) and titled (right) borders.
The titled border is used as-is here, without a title.

Both Aqua border styles create a recessed look. They differ only in the size of their margins above and inside the group. "InsetBorder.aquaVariant" is intended for use as an untitled group border, while "TitledBorder.aquaVariant" is intended for a titled group.

JPanel titledGroup = new JPanel( );
Border aquaBorder = UIManager.getBorder( "TitledBorder.aquaVariant" );
titledGroup.setBorder( new TitledBorder( aquaBorder, "Title" ) );
Aqua titled border
Figure 6. Apple's titled border with a title.

Note that titled borders using Apple's recessed border automatically put the title above the border, instead of on top of it. This is the correct behavior for group titles on a Mac.

Using other borders on non-Macs

Naturally, if your Java code is intended to run on non-Macs as well, you'll need to revert to some other border style (probably EtchedBorder) if getBorder( ) on UIManager returns null.

JPanel titledGroup = new JPanel( );
Border border = UIManager.getBorder( "TitledBorder.aquaVariant" );
if ( border == null )
    border = new EtchedBorder( );
titledGroup.setBorder( new TitledBorder( border, "Title" ) );

Aqua's recessed borders add their own margins, while Java's other borders do not. To compensate, you may need to adjust your inner margins when you use Aqua borders.

Using recessed borders on tabs

JTabbedPane manages a set of tabs that are typically each a JPanel. In Aqua, the tabs line up along the top of a recessed border.

To get this look from Java... do nothing! Apple's "Mac OS X" look and feel automatically creates a recessed border for the tabs. There's nothing more you need to do.

JTabbedPane tabs = new JTabbedPane( );
tabs.addTab( "Tab 1", firstTab );
tabs.addTab( "Tab 2", secondTab );
tabs.addTab( "Tab 3", thirdTab );
Aqua tabs
Figure 7. Apple's tabs with a recessed border.

Handling the quirks of Aqua borders

Aqua recessed borders shade the interior a bit darker than the normal background color. For components with transparent backgrounds, this darker shade shows through just fine. But if you include an opaque component, such as a JPanel, it will draw a block of lighter colored background atop this darker shade and look odd.

The solution is to make components inside the group non-opaque by calling setOpaque( false ):

JPanel innerPanel = new JPanel( );
innerPanel.setOpaque( false );
Opaque and transparent inner panels
Figure 8. Apple's titled border with an opaque (top) and
non-opaque (bottom) inner JPanel.

Further reading

Related articles at

Web articles and specifications


Aqua style titled border as default

Great article!

One thing to add: You can also set the Aqua style titled border as a default, so it will be used whenever you create a TitledBorder:

UIManager.put("TitledBorder.border", UIManager.getBorder("TitledBorder.aquaVariant"));

BorderFactory.createTitledBorder("This will be Aqua style now");


This was super useful information

I also have:

defaults.put("TitledBorder.font", defaults.get("SmallSystemFont"));

Because for some reason, the default value for TitledBorder.font is the normal system font size, even though on Mac OS, the titles on all those things are consistently the small font.

Also if you happen to be using JXTitledPanel from SwingX and aren't messing with any of the special stuff it has (i.e. if you are only using it as a convenient way to insert bordered panels), you can subclass BasicTitledPaneUI like this:

Thank you so much for the

Thank you so much for the wonderful tutorial for the Mac Java tip and how to create Aqua recessed borders in it. This certainly helped to increase my knowledge and helped me to make my system more good to look at. anti snoring

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