< Previous PageNext Page > Hide TOC

User Interface Toolkits for Java

This article discusses how the Mac OS X implementation of the user interface toolkits Swing, AWT, accessibility, and sound differ from the toolkits on other platforms. Although there is some additional functionality in Mac OS X, for the most part these toolkits work as you would expect them to on other platforms. This article does not discuss user interface design issues that you should consider in Mac OS X. For that information, see “Making User Interface Decisions.”

Contents:

Swing
Abstract Window Toolkit (AWT)
Character Encoding
Accessibility
Security
Sound
Input Methods
Java 2D
Resolution Independence


Swing

In Mac OS X, Swing uses the Aqua Look and Feel as the default look and feel (LAF). Swing attempts to be platform neutral, but some aspects of it are an impedance mismatch with the Aqua user interface. Apple attempts to bridge the gap with a common ground that provides both developers and users an experience that is not foreign. This section discusses where the Aqua LAF differs from the default implementation on other platforms.

Note: While testing your application, you should test it on the standard Java cross-platform LAF as well as Aqua. To do this, add UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassname()) to your code.

Menu Bars (JMenuBar)

In Java’s default cross-platform LAF, as well as the Windows LAF, menus are applied on a per-frame basis inside the window under the title bar. On a Mac, in contrast, menus appear in one spot no matter what windows users have open—at the top of the screen, in the menu bar.

To get menus out of the window and into the menu bar, you need only to set a single system property:

apple.laf.useScreenMenuBar

This property can have a value of true or false. By default, it is false, which means menus are in the window instead of the menu bar. When this property is set to true, the Java runtime moves the menu bar of any Java frame to the top of the screen, where Macintosh users expect it. Since this is just a simple runtime property that only the Mac OS X Java VM looks for, there is no harm in putting it into your cross-platform code base.

Note that this setting does not work for Java dialogs having menus. A dialog should be informational or present the user with a simple decision, not provide complex choices. If users are performing actions in a dialog, it is not really a dialog and you should consider using a JFrame object instead of a JDialog object.

Tabbed Panes (JTabbedPane)

On other platforms, if you have a tabbed pane (JTabbedPane) with too many tabs to fit in the parent window, the tabs are simply stacked on top of each other. In the Aqua user interface of Mac OS X, tab controls are never stacked. The Aqua LAF implementation of multiple tabs includes a special tab on the right that exposes a pull-down menu to navigate to the tabbed panes not visible. This behavior, allows you to program your application just as you would on any other platform while providing users an experience that is more consistent with Mac OS X guidelines. The difference between a tabbed pane in Mac OS X and a tabbed pane in Windows is shown in Figure 1.


Figure 1  Tabbed panes with multiple tabs in Mac OS X and Windows

A tabbed pane with multiple tabs on another platform

One other thing to keep in mind about JTabbedPane objects in Mac OS X is that they have a standard size. If you put an image in a tab, the image is scaled to fit the tab instead of the tab to the image. This standard size applies to several other Swing components as well.

Component Sizing

Aqua has very well-defined guidelines for the size of its controls. Swing, on the other hand, does not. The Aqua LAF tries to find a common ground. For example, since any combo box larger than twenty pixels would look out of place in Mac OS X, that is all that is displayed, even if the actual size of the combo box is bigger. Figure 2 shows a very large JComboBox component in Windows XP. Note that the drop-down scrolling list appears at the bottom of the button.


Figure 2  An oversize JComboBox component in Windows

Oversize JComboBox in Windows

The same code yields quite a different look in Mac OS X, as can be seen in Figure 3. The visible button is sized to that of a standard Aqua combo box. The drop-down list appears at the bottom of the visible button. The entire area that is active on other platforms is still active, but the button itself doesn’t appear as large.


Figure 3  An oversize JComboBox component in the Aqua LAF

Oversize JComboBox in the Aqua LAF

Note that some other components have similar sizing adjustments to align with the standards set in Apple Human Interface Guidelines for example, scroller and sliders. The JComboBox example is an extreme example. Most are not as large, but this gives you an idea of how the Aqua LAF handles this type of situation.

Buttons

There are basically three button types in Mac OS X:

To be consistent with these button types and their defined use in Mac OS X, there are some nuances of Swing buttons that you should be aware of:

In addition to these default characteristics which are dependent on height and the contents of the button, you can also explicitly set the type of button with JButton.buttontype, which accepts three values:

Keep Apple’s human interface guidelines in mind if you explicitly set a button type.

For a more thorough treatment of the Aqua LAF in Swing, see New Control Styles available within J2SE 5.0 on Mac OS X 10.5.

Abstract Window Toolkit (AWT)

By its nature, AWT is very different on every platform. When developing Java applications in Mac OS X, follow these tips for best results:

Character Encoding

The default character encoding in Java for Mac OS X is MacRoman. The default font encoding on some other platforms is ISO-Latin-1 or WinLatin-1; unlike MacRoman, these encodings are subsets of UTF-8. Programs that assume that filenames can be turned into UTF-8 by just turning a byte into a char will cause problems in Mac OS X.

The simplest way to work around this problem is to specify a font encoding explicitly rather than assuming one.

If you do not specify a font encoding explicitly, recognize that:

Accessibility

With some platforms, to use the Java Accessibility API, you must use a native bridge. This is not necessary in Mac OS X because the bridging code is built in. Users can configure the accessibility features of Mac OS X through the Universal Access pane of System Preferences. As a result, if you are using the Accessibility API, your application can use devices that the user has configured there.

Beginning with Mac OS X v10.4, a screen reader called VoiceOver is included with the operating system. Your Java application automatically uses this technology.

Security

In Mac OS X v10.5, Java applications that use the Kerberos computer network authentication protocol automatically access the system credentials cache and tickets.

Apple also includes a cryptographic service provider based on the Java Cryptography Architecture. Currently, the following algorithms are supported:

Java on Mac OS X v10.5 features an implementation of KeyStore that uses the Mac OS X Keychain as its permanent store. You can get an instance of this implementation by using code like this:

keyStore = KeyStore.getInstance("KeychainStore", "Apple");

For more usage information, see the reference documentation on java.security.KeyStore at http://java.sun.com/j2se/1.5.0/docs/api/java/security/KeyStore.html.

Sound

Java on Mac OS X allows you to sample sound with Apple’s Core Audio framework at any frame rate supported by your input device. Input can be signed or unsigned PCM encoding, mono or stereo, 8 or 16 bits per sample.

By default, the Java Sound engine in Mac OS X uses the midsize sound bank from http://java.sun.com/products/java-media/sound/soundbanks.html.

Input Methods

Mac OS X supports Java input methods. The utility application Input Method Hot Key, installed in /Applications/Utilities/Java/, allows you to configure a trigger for input methods. You can download sample input methods from http://java.sun.com/products/jfc/tsc/articles/InputMethod/inputmethod.html.

Java 2D

In Mac OS X, Java windows are double buffered. The Java implementation itself attempts to flush the buffer to the screen often enough to have good drawing behavior without compromising performance. If, for some reason, you need to force window buffers to be flushed immediately, use Toolkit.sync.

By default, Java on Mac OS X uses the Sun2D renderer, which exactly mimics the behavior of Java 2D on other platforms. If you are developing a graphically intensive application specifically for the Mac OS X platform and the Sun2D renderer’s performance is inadequate, you may find better success using Apple’s Quartz graphics engine for your Java rendering instead (see http://developer.apple.com/graphicsimaging/quartz/ for more information). Quartz is optimized for a different set of operations from the Sun2D renderer, and as a consequence its behavior is by no means identical to that of Java on other platforms.

By default, Quartz displays text anti-aliased. Therefore, if you use Quartz as your renderer, Java2D turns anti-aliasing on in order to render text in the Aqua look and feel for Swing (it does this by setting KEY_ANTIALIASING to VALUE_ANTIALIAS_ON). If you want the pixels of your images and text to more closely approximate that same content on other platforms, turn off anti-aliasing. You can do so by using the properties described in Java System Properties or by calling java.awt.Graphics.setRenderingHint from within your Java application. In applets, anti-aliasing is turned off by default.

Tip: When you are using anti-aliasing, if you need to replace text or an image, repaint the graphics context. Do not use XOR mode to repaint images.

Resolution Independence

Java is not explicitly designed for resolution independence (also known as HiDPI); therefore, Java for Mac OS X borrows some functionality from the Cocoa framework. To load a resolution-independent tiff, icns, or pdf file from the Resources folder of your application bundle into your Java application, use the getImage method of java.awt.Toolkit. The string you pass into getImage is of the form "NSImage://MyImage". Do not include the file extension of the image. Also be aware that if you are using the Sun2D renderer, Java will automatically switch to the Quartz engine and enable anti-aliasing if you load a resolution-independent image.

You can test resolution independence in your application with the Quartz Debug tool, located in /Developer/Applications/Performance Tools. Quartz Debug allows you to launch your application at up to three times the default screen resolution. For a full list of features included in Quartz Debug, consult the Quartz Debug Help.

Mac OS X includes resolution-independent standard images for user interfaces that you can also access with the getImage method of java.awt.Toolkit. For instance, Toolkit.getDefaultToolkit().getImage("NSImage://NSColorPanel") will return an Image reference representing the color wheel icon seen on the Colors button in applications such as Mail. For a comprehensive list of the standard images available, see “Constants” in NSImage Class Reference.

Note: The standard image constants defined in NSImage.h all include the substring ImageName. For instance, the constant for the NSColorPanel image has the name NSImageNameColorPanel. When passing a string to getImage, do not include ImageName in the string—it is included in the name of the Objective-C constant, but not the value of the name itself.



< Previous PageNext Page > Hide TOC


© 2003, 2008 Apple Inc. All Rights Reserved. (Last updated: 2008-10-15)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.