Uses reflection and JavaBeans introspection to : JavaBean « Reflection « Java






Uses reflection and JavaBeans introspection to

Uses reflection and JavaBeans introspection to
 
/*
 * Copyright (c) 2000 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 2nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book (recommended),
 * visit http://www.davidflanagan.com/javaexamples2.
 */

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Vector;

import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

/**
 * This class is a program that uses reflection and JavaBeans introspection to
 * create a set of named components, set named properties on those components,
 * and display them. It allows the user to view the components using any
 * installed look-and-feel. It is intended as a simple way to experiment with
 * AWT and Swing components, and to view a number of the other examples
 * developed in this chapter. It also demonstrates frames, menus, and the
 * JTabbedPane component.
 */
public class ShowComponent {
  // The main program
  public static void main(String[] args) {
    // Process the command line to get the components to display
    Vector components = getComponentsFromArgs(args);

    // Create a frame (a window) to display them in
    JFrame frame = new JFrame("ShowComponent");

    // Handle window close requests by exiting the VM
    frame.addWindowListener(new WindowAdapter() { // Anonymous inner class
          public void windowClosing(WindowEvent e) {
            System.exit(0);
          }
        });

    // Set up a menu system that allows the user to select the
    // look-and-feel of the component from a list of installed PLAFs
    JMenuBar menubar = new JMenuBar(); // Create a menubar
    frame.setJMenuBar(menubar); // Tell the frame to display it
    JMenu plafmenu = createPlafMenu(frame); // Create a menu
    menubar.add(plafmenu); // Add the menu to the menubar

    // Create a JTabbedPane to display each of the components
    JTabbedPane pane = new JTabbedPane();

    // Now add each component as a tab of the tabbed pane
    // Use the unqualified component classname as the tab text
    for (int i = 0; i < components.size(); i++) {
      Component c = (Component) components.elementAt(i);
      String classname = c.getClass().getName();
      String tabname = classname
          .substring(classname.lastIndexOf('.') + 1);
      pane.addTab(tabname, c);
    }

    // Add the tabbed pane to the frame. Note the call to getContentPane()
    // This is required for JFrame, but not for most Swing components
    frame.getContentPane().add(pane);

    // Set the frame size and pop it up
    frame.pack(); // Make frame as big as its kids need
    frame.setVisible(true); // Make the frame visible on the screen

    // The main() method exits now but the Java VM keeps running because
    // all AWT programs automatically start an event-handling thread.
  }

  /**
   * This static method queries the system to find out what Pluggable
   * Look-and-Feel (PLAF) implementations are available. Then it creates a
   * JMenu component that lists each of the implementations by name and allows
   * the user to select one of them using JRadioButtonMenuItem components.
   * When the user selects one, the selected menu item traverses the component
   * hierarchy and tells all components to use the new PLAF.
   */
  public static JMenu createPlafMenu(final JFrame frame) {
    // Create the menu
    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();

    // 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
      JMenuItem item = plafmenu.add(new JRadioButtonMenuItem(plafName));

      // Tell the menu item what to do when it is selected
      item.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          try {
            // Set the new look and feel
            UIManager.setLookAndFeel(plafClassName);
            // Tell each component to change its look-and-feel
            SwingUtilities.updateComponentTreeUI(frame);
            // Tell the frame to resize itself to the its
            // children's new desired sizes
            frame.pack();
          } catch (Exception ex) {
            System.err.println(ex);
          }
        }

      });

      // Only allow one menu item to be selected at once
      radiogroup.add(item);
    }
    return plafmenu;
  }

  /**
   * This method loops through the command line arguments looking for class
   * names of components to create and property settings for those components
   * in the form name=value. This method demonstrates reflection and JavaBeans
   * introspection as they can be applied to dynamically created GUIs
   */
  public static Vector getComponentsFromArgs(String[] args) {
    Vector components = new Vector(); // List of components to return
    Component component = null; // The current component
    PropertyDescriptor[] properties = null; // Properties of the component
    Object[] methodArgs = new Object[1]; // We'll use this below

    nextarg: // This is a labeled loop
    for (int i = 0; i < args.length; i++) { // Loop through all arguments
      // If the argument does not contain an equal sign, then it is
      // a component class name. Otherwise it is a property setting
      int equalsPos = args[i].indexOf('=');
      if (equalsPos == -1) { // Its the name of a component
        try {
          // Load the named component class
          Class componentClass = Class.forName(args[i]);
          // Instantiate it to create the component instance
          component = (Component) componentClass.newInstance();
          // Use JavaBeans to introspect the component
          // And get the list of properties it supports
          BeanInfo componentBeanInfo = Introspector
              .getBeanInfo(componentClass);
          properties = componentBeanInfo.getPropertyDescriptors();
        } catch (Exception e) {
          // If any step failed, print an error and exit
          System.out.println("Can't load, instantiate, "
              + "or introspect: " + args[i]);
          System.exit(1);
        }

        // If we succeeded, store the component in the vector
        components.addElement(component);
      } else { // The arg is a name=value property specification
        String name = args[i].substring(0, equalsPos); // property name
        String value = args[i].substring(equalsPos + 1); // property
                                 // value

        // If we don't have a component to set this property on, skip!
        if (component == null)
          continue nextarg;

        // Now look through the properties descriptors for this
        // component to find one with the same name.
        for (int p = 0; p < properties.length; p++) {
          if (properties[p].getName().equals(name)) {
            // Okay, we found a property of the right name.
            // Now get its type, and the setter method
            Class type = properties[p].getPropertyType();
            Method setter = properties[p].getWriteMethod();

            // Check if property is read-only!
            if (setter == null) {
              System.err.println("Property " + name
                  + " is read-only");
              continue nextarg; // continue with next argument
            }

            // Try to convert the property value to the right type
            // We support a small set of common property types here
            // Store the converted value in an Object[] so it can
            // be easily passed when we invoke the property setter
            try {
              if (type == String.class) { // no conversion needed
                methodArgs[0] = value;
              } else if (type == int.class) { // String to int
                methodArgs[0] = Integer.valueOf(value);
              } else if (type == boolean.class) { // to boolean
                methodArgs[0] = Boolean.valueOf(value);
              } else if (type == Color.class) { // to Color
                methodArgs[0] = Color.decode(value);
              } else if (type == Font.class) { // String to Font
                methodArgs[0] = Font.decode(value);
              } else {
                // If we can't convert, ignore the property
                System.err.println("Property " + name
                    + " is of unsupported type "
                    + type.getName());
                continue nextarg;
              }
            } catch (Exception e) {
              // If conversion failed, continue with the next arg
              System.err.println("Can't convert  '" + value
                  + "' to type " + type.getName()
                  + " for property " + name);
              continue nextarg;
            }

            // Finally, use reflection to invoke the property
            // setter method of the component we created, and pass
            // in the converted property value.
            try {
              setter.invoke(component, methodArgs);
            } catch (Exception e) {
              System.err.println("Can't set property: " + name);
            }

            // Now go on to next command-line arg
            continue nextarg;
          }
        }

        // If we get here, we didn't find the named property
        System.err.println("Warning: No such property: " + name);
      }
    }

    return components;
  }
}
           
         
  








Related examples in the same category

1.Get Color
2.Returns attribute's setter method. If the method not found then NoSuchMethodException will be thrown.
3.Returns attribute's getter method. If the method not found then NoSuchMethodException will be thrown.