Recipe 14.15 Changing a Swing Program's Look and FeelProblemYou want to change the look and feel of an application. SolutionUse the static UIManager.setLookAndFeel( ) method. Maybe. DiscussionIf 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 the scope of 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 it 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):
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 JDK) offers a menu item to change its look and feel. Figure 14-13 is my nice little program in the Java style; see Example 14-8 for the source code. Figure 14-13. Java, Windows, and Motif look and feel under WindowsOf course, not all looks work on all platforms. If I try the Mac OS look and feel under Windows, I get the error dialog shown in Figure 14-14, which shows what happens when you request any look and feel that is unavailable on the current platform. Figure 14-14. Look and feel request refused on WindowsThe OPEN LOOK design alluded to in the code is, well, not written yet. Vaporware. That's why it's grayed out. Under Mac OS X, the default look and feel is, of course, the Mac OS look and feel. You can also select the Java or Motif look, but not the Windows look. See Figure 14-15. Figure 14-15. Look and feel switcher under Mac OS XExample 14-8 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 selects is not available. Example 14-8. LNFSwitcher.java/** * A Look-and-feel switcher. * @author Ian Darwin, http://www.darwinsys.com/ * @version $Id: ch14.xml,v 1.6 2004/05/07 15:20:56 ian Exp $ */ 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.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 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("Sun-MacOS"); bMac.addActionListener(new LNFSetter( "com.sun.java.swing.plaf.mac.MacLookAndFeel", bMac)); bg.add(bMac); cp.add(bMac); String defaultLookAndFeel = UIManager.getSystemLookAndFeelClassName( ); // System.out.println(defaultLookAndFeel); JRadioButton bDefault = new JRadioButton("Default"); bDefault.addActionListener(new LNFSetter( defaultLookAndFeel, bDefault)); bg.add(bDefault); cp.add(bDefault); previousButton = bDefault; bDefault.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); theFrame.pack( ); } 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( ); } } See AlsoSome alternate look-and-feel implementations can be found on the Web. If you'd like to build your own look and feel, perhaps for corporate identity reasons, some of these, in conjunction with O'Reilly's Java Swing, would be a good starting point. |