A number of the examples in this chapter have used the utility class LookAndFeelPrefs to install the user's preferred look-and-feel and create a JMenu listing available look-and-feel choices. LookAndFeelPrefs is shown in Example 11-29. It demonstrates the use of the javax.swing.UIManager class for querying and setting look-and-feels, and also demonstrates the use of the java.util.prefs package (new in Java 1.4) for retrieving and storing persistent user preferences. LookAndFeelPrefs relies on the list of installed look-and-feel implementations returned by UIManager.getInstalledLookAndFeels( ). By default (in Java 1.4.2, at least) this method returns three look-and-feels: the Java "Metal" look-and-feel, the Motif (CDE) look-and-feel, and the Windows look-and-feel. This is true even on non-Windows platforms for which the Windows look-and-feel is unsupported. Java 1.4.2 also ships with a GTK look-and-feel, which mimics the Linux GTK look-and-feel, but getInstalledLookAndFeels( ) does not know about it. To make this new look-and-feel available to the LookAndFeelPrefs example, you'll need to create a swing.properties file and place it in the jre/lib/ directory of your Java SDK. The contents of the file should look like this: # Add the Mac look-and-feel if your SDK comes with it. # Delete the Windows look-and-feel if it is not supported on your platform. swing.installedlafs = gtk,metal,motif,win swing.installedlaf.gtk.name = GTK Look and Feel, swing.installedlaf.gtk.class = com.sun.java.swing.plaf.gtk.GTKLookAndFeel swing.installedlaf.metal.name = Java Look and Feel swing.installedlaf.metal.class = javax.swing.plaf.metal.MetalLookAndFeel swing.installedlaf.motif.name = Motif/CDE Look and Feel swing.installedlaf.motif.class = com.sun.java.swing.plaf.motif.MotifLookAndFeel swing.installedlaf.win.name = Windows Look and Feel swing.installedlaf.win.class = com.sun.java.swing.plaf.windows.WindowsLookAndFeel Example 11-29. LookAndFeelPrefs.javapackage je3.gui; import javax.swing.*; import java.awt.event.*; import java.util.prefs.Preferences; public class LookAndFeelPrefs { public static final String PREF_NAME = "preferredLookAndFeelClassName"; /** * Get the desired look-and-feel from a per-user preference. If * the preference doesn't exist or is unavailable, use the * default look-and-feel. The preference is shared by all classes * in the same package as prefsClass. **/ public static void setPreferredLookAndFeel(Class prefsClass) { Preferences prefs=Preferences.userNodeForPackage(prefsClass); String defaultLAF = UIManager.getSystemLookAndFeelClassName( ); String laf = prefs.get(PREF_NAME, defaultLAF); try { UIManager.setLookAndFeel(laf); } catch (Exception e) { // ClassNotFound or InstantiationException // An exception here is probably caused by a bogus preference. // Ignore it silently; the user will make do with the default LAF. } } /** * Create a menu of radio buttons listing the available Look and Feels. * When the user selects one, change the component hierarchy under frame * to the new LAF, and store the new selection as the current preference * for the package containing class c. **/ public static JMenu createLookAndFeelMenu(final Class prefsClass, final ActionListener listener) { // Create the menu final JMenu plafmenu = new JMenu("Look and Feel"); // Create an object used for radio button mutual exclusion ButtonGroup radiogroup = new ButtonGroup( ); // Look up the available look-and-feels UIManager.LookAndFeelInfo[ ] plafs=UIManager.getInstalledLookAndFeels( ); // Find out which one is currently used String currentLAFName=UIManager.getLookAndFeel( ).getClass( ).getName( ); // Loop through the plafs, and add a menu item for each one for(int i = 0; i < plafs.length; i++) { String plafName = plafs[i].getName( ); final String plafClassName = plafs[i].getClassName( ); // Create the menu item final JMenuItem item = plafmenu.add(new JRadioButtonMenuItem(plafName)); item.setSelected(plafClassName.equals(currentLAFName)); // Tell the menu item what to do when it is selected item.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent event) { // Set the new look-and-feel try { UIManager.setLookAndFeel(plafClassName); } catch(UnsupportedLookAndFeelException e) { // Sometimes a Look-and-Feel is installed but not // supported, as in the Windows LaF on Linux platforms. JOptionPane.showMessageDialog(plafmenu, "The selected Look-and-Feel is " + "not supported on this platform.", "Unsupported Look And Feel", JOptionPane.ERROR_MESSAGE); item.setEnabled(false); } catch (Exception e) { // ClassNotFound or Instantiation item.setEnabled(false); // shouldn't happen } // Make the selection persistent by storing it in prefs. Preferences p = Preferences.userNodeForPackage(prefsClass); p.put(PREF_NAME, plafClassName); // Invoke the supplied action listener so the calling // application can update its components to the new LAF // Reuse the event that was passed here. listener.actionPerformed(event); } }); // Only allow one menu item to be selected at once radiogroup.add(item); } return plafmenu; } } |