FileDocCategorySizeDatePackage
ShowBean.javaAPI DocExample12431Sat Jan 24 10:44:34 GMT 2004je3.gui

ShowBean

public class ShowBean extends JFrame
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.

Fields Summary
List
beans
JMenu
propertyMenu
JMenu
commandMenu
JTabbedPane
pane
JFileChooser
fileChooser
Constructors Summary
public ShowBean(List beans)


    // Most initialization code is in the constructor instead of main()
        
	super("ShowBean");
	
	this.beans = beans;  // Save the list of Bean objects

	// Create a menubar
	JMenuBar menubar = new JMenuBar();    
	this.setJMenuBar(menubar);            // Tell the frame to display it

	// Create and populate a File menu
	JMenu filemenu = new JMenu("File");
	filemenu.setMnemonic('F");
	JMenuItem save = new JMenuItem("Save as...");
	save.setMnemonic('S");
	JMenuItem serialize = new JMenuItem("Serialize as...");
	JMenuItem quit = new JMenuItem("Quit");
	quit.setMnemonic('Q");
	menubar.add(filemenu);
	filemenu.add(save);
	filemenu.add(serialize);
	filemenu.add(new JSeparator());
	filemenu.add(quit);

	// Here are event handlers for the Save As and Quit menu items
	save.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    saveCurrentPane();
		}
	    });
	serialize.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    serializeCurrentPane();
		}
	    });
	quit.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    System.exit(0);
		}
	    });

	// Set up a menu that allows the user to select the look-and-feel of
	// the component from a list of installed look-and-feels.
	// Remember the selected LAF in a persistent Preferences node.
	JMenu plafmenu =
	  LookAndFeelPrefs.createLookAndFeelMenu(ShowBean.class,
	      new ActionListener() {
		  public void actionPerformed(ActionEvent event) {
		      // When the user selects a new LAF, tell each
		      // component to change its look-and-feel
		      SwingUtilities.updateComponentTreeUI(ShowBean.this);
		      // Then repack the frame to its new preferred size.
		      ShowBean.this.pack();
		  }
	      });
	plafmenu.setMnemonic('L");
	menubar.add(plafmenu);                // Add the menu to the menubar

	// Create the Properties and Commands menus, but don't populate them.
	// JMenuItems are added each time a new tab is selected.
	propertyMenu = new JMenu("Properties");
	propertyMenu.setMnemonic('P");
	menubar.add(propertyMenu);
	commandMenu = new JMenu("Commands");
	commandMenu.setMnemonic('C");
	menubar.add(commandMenu);
	
	// Some components have many properties, so make the property menu
	// three columns wide so that we can see all of the entries.
	propertyMenu.getPopupMenu().setLayout(new GridLayout(0,3));

	// Create a JTabbedPane to display each of the components
	pane = new JTabbedPane();
	pane.addChangeListener(new ChangeListener() {
		public void stateChanged(ChangeEvent e) {
		    populateMenus(pane.getSelectedIndex());
		}
	    });

	// Now add each component as a tab of the tabbed pane
	for(int i = 0; i < beans.size(); i++) {
	    Bean b = (Bean) beans.get(i);
	    Object o = b.getBean();
	    Component component;
	    if (o instanceof Component) component = (Component) o;
	    else component = new JLabel("This bean has no Component");
	    Image image = b.getIcon();
	    Icon icon = null;
	    if (image != null) icon = new ImageIcon(image);
	    pane.addTab(b.getDisplayName(),         // text for the tab
			icon,                       // icon for the tab
			component,                  // contents of the tab
			b.getShortDescription());   // tooltip for the tab
	}

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

	this.pack();   // Make frame as big as its kids need 
    
Methods Summary
voideditProperty(je3.beans.Bean bean, java.lang.String name)

	try {
	    if (bean.isReadOnly(name)) {
		String value = bean.getPropertyValue(name);
		JOptionPane.showMessageDialog(this, name + " = " + value,
					      "Read-only Property Value",
					      JOptionPane.PLAIN_MESSAGE);
	    }
	    else {
		Component editor = bean.getPropertyEditor(name);
		JOptionPane.showMessageDialog(this,
					      new Object[] { name, editor},
					      "Edit Property",
					      JOptionPane.PLAIN_MESSAGE);
	    }
	}
	catch(Exception e) {
	    getToolkit().beep();
	    JOptionPane.showMessageDialog(this, e, e.getClass().getName(),
					  JOptionPane.ERROR_MESSAGE);
	}
    
static java.util.ListgetBeansFromArgs(java.lang.String[] args)
This static method loops through the command line arguments looking for the names of files that contain XML encoded or serialized components, or for class names of components to instantiate or for name=value property settings for those components. It relies on the Bean class developed elsewhere.

	List beans = new ArrayList();      // List of beans to return
	Bean bean = null;                  // The current bean
	boolean expert = false;

	for(int i = 0; i < args.length; i++) {  // Loop through all arguments
	    if (args[i].charAt(0) == '-") { // Does it begin with a dash?
		try { 
		    if (args[i].equals("-expert")) {
			expert = true;
		    }
		    else if (args[i].equals("-xml")) { // read from xml
			if (++i >= args.length) continue;
			InputStream in = new FileInputStream(args[i]);
			bean = Bean.fromPersistentStream(in, expert);
			beans.add(bean);
			in.close();
		    }
		    else if (args[i].equals("-ser")) {  // deserialize a file
			if (++i >= args.length) continue;
			ObjectInputStream in =
			   new ObjectInputStream(new FileInputStream(args[i]));
			bean = Bean.fromSerializedStream(in, expert);
			beans.add(bean);
			in.close();
		    }
		    else {
			System.err.println("Unknown option: " + args[i]);
			continue;
		    }
		}
		catch(Exception e) {  // In case anything goes wrong
		    System.err.println(e);
		    System.exit(1);
		    continue;
		}
	    }
	    else if (args[i].indexOf('=") == -1){ // Its a component name
		// If the argument does not contain an equal sign, then it is
		// a component class name.
		try {
		    bean = Bean.forClassName(args[i], expert);
		    beans.add(bean);
		}
		catch(Exception e) {  
		    // If any step failed, print an error and exit
		    System.out.println("Can't load, instantiate, " +
				       "or introspect: " + args[i]);
		    System.out.println(e);
		    System.exit(1);
		}
	    }
	    else { // The arg is a name=value property specification 
		// Break into name and value parts
		int pos = args[i].indexOf('=");
		String name = args[i].substring(0, pos); // property name
		String value = args[i].substring(pos+1); // property value
		    
		// If we don't have a component to set this property on, skip!
		if (bean == null) {
		    System.err.println("Property " + name + 
				       " specified before any bean.");
		    continue;
		}

		// Now try to set the property
		try { bean.setPropertyValue(name, value); }
		catch(Exception e) {
		    // Failure to set a property is not a fatal error;
		    // Just display the message and continue
		    System.out.println(e);
		}
	    }
	}
	
	return beans;
    
public static voidmain(java.lang.String[] args)

	// Set the look-and-feel for the application.  
	// LookAndFeelPrefs is defined elsewhere in this package.
	LookAndFeelPrefs.setPreferredLookAndFeel(ShowBean.class);

	// Process the command line to get the components to display
	List beans = getBeansFromArgs(args);

	JFrame frame = new ShowBean(beans);  // Create frame

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

	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.
    
voidpopulateMenus(int index)
Create JMenuItem objects in the Properties and Command menus. This method is called whenever a new tab is selected.

	// First, delete the old menu contents
	propertyMenu.removeAll();
	commandMenu.removeAll();

	// The Bean object for this tab
	final Bean bean = (Bean) beans.get(index);

	List props = bean.getPropertyNames();
	for(int i = 0; i < props.size(); i++) {
	    final String name = (String)props.get(i);
	    // Create a menu item for the command
	    JMenuItem item = new JMenuItem(name);
	    // If the property has a non-trivial description, make it a tooltip
	    String tip = bean.getPropertyDescription(name);
	    if (tip != null && !tip.equals(name)) item.setToolTipText(tip);

	    item.addActionListener(new ActionListener() {
		    public void actionPerformed(ActionEvent e) {
			editProperty(bean, name);
		    }
		});

	    propertyMenu.add(item);
	}

	List commands = bean.getCommandNames();
	for(int i = 0; i < commands.size(); i++) {
	    final String name = (String)commands.get(i);
	    // Create a menu item for the command
	    JMenuItem item = new JMenuItem(name);
	    // If the command has a non-trivial description, make it a tooltip
	    String tip = bean.getCommandDescription(name);
	    if (tip != null && !name.endsWith(tip)) item.setToolTipText(tip);

	    // Invoke the command when the item is selected
	    item.addActionListener(new ActionListener() {
		    public void actionPerformed(ActionEvent e) {
			try { bean.invokeCommand(name); }
			catch(Exception ex) {
			    getToolkit().beep();
			    JOptionPane.showMessageDialog(ShowBean.this,
						ex, ex.getClass().getName(),
						JOptionPane.ERROR_MESSAGE);
			}
		    }
		});
	    // Add the item to the menu
	    commandMenu.add(item);
	}
	if (commands.size() == 0)
	    commandMenu.add("No Commands Available");
    
public voidsaveCurrentPane()
Ask the user to select a filename, and then save the contents of the current tab to that file using the JavaBeans persistence mechanism.

	int result = fileChooser.showSaveDialog(this);
	if (result == JFileChooser.APPROVE_OPTION) {
	    try {
		File file = fileChooser.getSelectedFile();
		XMLEncoder encoder=new XMLEncoder(new FileOutputStream(file));
		encoder.writeObject(pane.getSelectedComponent());
		encoder.close();
	    }
	    catch(IOException e) {
		JOptionPane.showMessageDialog(this, e, e.getClass().getName(),
					      JOptionPane.ERROR_MESSAGE);
	    }
	}
    
public voidserializeCurrentPane()
Ask the user to choose a filename, and then save the contents of the current pane to that file using traditional object serialization

	int result = fileChooser.showSaveDialog(this);
	if (result == JFileChooser.APPROVE_OPTION) {
	    try {
		File file = fileChooser.getSelectedFile();
		ObjectOutputStream out =
		    new ObjectOutputStream(new FileOutputStream(file));
		out.writeObject(pane.getSelectedComponent());
		out.close();
	    }
	    catch(IOException e) {
		JOptionPane.showMessageDialog(this, e, e.getClass().getName(),
					      JOptionPane.ERROR_MESSAGE);
	    }
	}