Changing a Swing Program’s Look and Feel

Problem

You want to change the look and feel of an application.

Solution

Use the static UIManager.setLookAndFeel( ) method. Maybe.

Discussion

If you wish to specify the entire look and feel for a program, set it with the static UIManager.setLookAndFeel( ) method; the name you pass in must be the full name (as a string) of a class that implements a Java look and feel. The details of writing a look and feel class are beyond this book; refer to the book Java Swing or the Sun documentation. But using these classes is easy. For example:

UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");

This must appear before you create the GUI of the program, and can throw an exception if the class name is invalid.

People sometimes like to show off the fact that you can change the look and feel on the fly. You call setLookAndFeel( ) as previously, and then call the static SwingUtilities.updateComponentTree( ) for your JFrame and all detached trees, such as dialog classes. But before you rush out to do it, please be advised that the official Sun position is that you shouldn’t! The official Java Look and Feel Design Guideline book says, on page 23 (first edition):

Because there is far more to the design of an application than the look and feel of components, it is unwise to give end users the ability to swap look and feel while [running] your application. Switching look and feel designs in this way only swaps the look and feel designs from one platform to another. The layout and vocabulary used are platform-specific and do not change. For instance, swapping look and feel designs does not change the titles of the menus.

The book does recommend that you let users specify an alternate look and feel, presumably in your properties file, at program startup time. Even so, the capability to switch while an application is running is too tempting to ignore; even Sun’s own Swing Demonstration (included with the Java SDK) offers a menu item to change its look and feel. Figure 13-10 is my nice little program in the Java style; see Example 13-6 for the source code.

Java, MS-Windows, and Motif look and feel under MS-Windows

Figure 13-10. Java, MS-Windows, and Motif look and feel under MS-Windows

Figure 13-11 shows what happens when you request a look and feel that is unavailable on the current platform.

Look and feel request refused on MS-Windows

Figure 13-11. Look and feel request refused on MS-Windows

There’s a bit of a cheat here: I had to resize it to get the disabled OPEN LOOK radio button to appear, due to what I think is a bug in JDK 1.2. If I try the MacOS look and feel under MS-Windows, I get the error dialog shown in Figure 13-11.

The OPEN LOOK design alluded to in the code is, well, not written yet. Vaporware. That’s why it’s grayed out.

Under MacOS X, the default look and feel is, of course, the MacOS X look and feel. You can also select the Java or Motif look, but not the MS-Windows look. See Figure 13-12.

Look and feel switcher under MacOS X

Figure 13-12. Look and feel switcher under MacOS X

Example 13-6 shows the code that implements the look and feel switcher. It’s pretty straightforward based on what we’ve seen already. The only neat trick is that I’ve set the selected button back to what it was if the look and feel that the user selected is not available.

Example 13-6. LNFSwitcher.java

import com.darwinsys.util.*;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.metal.*;

/**
 * A Look-and-feel switcher.
 */
public class LNFSwitcher {
    /** The frame. */
    protected JFrame theFrame;
    /** Its content pane */
    protected Container cp;

    /** Start with the Java look-and-feel, if possible */
    final static String PREFERREDLOOKANDFEELNAME =
        "javax.swing.plaf.metal.MetalLookAndFeel";
    protected String curLF = PREFERREDLOOKANDFEELNAME;
    protected JRadioButton previousButton;

    /** Construct a program... */
    public LNFSwitcher(  ) {
        super(  );
        theFrame = new JFrame("LNF Switcher");
        theFrame.addWindowListener(new WindowCloser(theFrame, true));
        cp = theFrame.getContentPane(  );
        cp.setLayout(new FlowLayout(  ));

        ButtonGroup bg = new ButtonGroup(  );

        JRadioButton bJava = new JRadioButton("Java");
        bJava.addActionListener(new LNFSetter(
            "javax.swing.plaf.metal.MetalLookAndFeel", bJava));
        bg.add(bJava);
        cp.add(bJava);

        JRadioButton bMSW  = new JRadioButton("MS-Windows");
        bMSW.addActionListener(new LNFSetter(
            "com.sun.java.swing.plaf.windows.WindowsLookAndFeel", bMSW));
        bg.add(bMSW);
        cp.add(bMSW);

        JRadioButton bMotif = new JRadioButton("Motif");
        bMotif.addActionListener(new LNFSetter(
            "com.sun.java.swing.plaf.motif.MotifLookAndFeel", bMotif));
        bg.add(bMotif);
        cp.add(bMotif);

        JRadioButton bMac = new JRadioButton("MacOS");
        bMac.addActionListener(new LNFSetter(
            "com.sun.java.swing.plaf.mac.MacLookAndFeel", bMac));
        bg.add(bMac);
        cp.add(bMac);

        // Following is a **hypothetical** addition!
        JRadioButton bOL = new JRadioButton("OPEN LOOK");
        bOL.addActionListener(new LNFSetter(
             "com.darwinsys.openlook.OpenLookAndFeel", bOL));
        bOL.setEnabled(false);    // since it IS hypothetical
        bg.add(bOL);
        cp.add(bOL);

        // We "know" that the Java Look-and-feel is the default.
        previousButton = bJava;
        bJava.setSelected(true);

        theFrame.pack(  );
        theFrame.setVisible(true);
    }

    /* Class to set the Look and Feel on a frame */
    class LNFSetter implements ActionListener {
        String theLNFName;
        JRadioButton thisButton;

        /** Called to setup for button handling */
        LNFSetter(String lnfName, JRadioButton me) {
            theLNFName = lnfName;
            thisButton = me;
        }

        /** Called when the button actually gets pressed. */
        public void actionPerformed(ActionEvent e) {
            try {
                UIManager.setLookAndFeel(theLNFName);
                SwingUtilities.updateComponentTreeUI(theFrame);
            } catch (Exception evt) {
                JOptionPane.showMessageDialog(null,
                    "setLookAndFeel didn't work: " + evt,
                    "UI Failure", JOptionPane.INFORMATION_MESSAGE);
                previousButton.setSelected(true);        // reset the GUI to agree
            }
            previousButton = thisButton;
        }
    }

    public static void main(String[] argv) {
        new LNFSwitcher(  );
    }
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.232.11