Customizing the Windowing Toolkit

   

It's possible to customize the windowing toolkit by building new components, containers, layout managers, events, and listeners. All that customization could fill another entire book, so here only customized containers and layout managers will be discussed. If you would like to create your own lightweight components and learn about the AWT's lightweight UI framework, please visit the following Web site:

 http://java.sun.com/j2se/1.3/docs/guide/awt/designspec/lightweights.html 

Building Your Own Containers

You can create new containers that are lightweight (as opposed to the existing heavyweight dialog, file dialog, frame, scroll pane, and window containers). These new containers do not have corresponding peers, so they don't use up system resources. The simplest way to create a lightweight container is to subclass the Container class. This is shown in the following code fragment:

 public class myContainer extends Container { } 

Because lightweight containers do not have associated peers, they must be contained by heavyweight containers. The following code fragment creates an object from the myContainer class and adds it to a Frame object:

Caution

Because the new container does not have a layout manager, one must be specified. Otherwise, you'll never see the added components.


 myContainer panel = new myContainer (); panel.setLayout (new FlowLayout ()); panel.add (new Button ("Hello")); Frame f = new Frame (); f.add (panel); f.setSize (200, 200); f.setVisible (true); 

Building Your Own Layout Managers

If you're dissatisfied with the existing layout managers provided by the windowing toolkit, you can create your own. To create a layout manager, you need to construct a class that implements the LayoutManager interface. This interface provides the following five methods :

 void addLayoutComponent (String name, Component comp) void removeLayoutComponent (Component comp) Dimension preferredLayoutSize (Container parent) Dimension minimumLayoutSize (Container parent) void layoutContainer (Container parent) 

The following method is called by a container's add (String name, Component comp) method. The name is used to provide constraint information, such as a position in which to place comp ”north, south, left, right, top, bottom, and so on. In response, this method saves name and comp in an internal data structure. If the layout manager does not use constraints, this method can be stubbed out, forcing the container to store comp.

 void addLayoutComponent (String name, Component comp) 

The following method is called by the container's remove and removeAll methods. Information previously stored in internal data structures by addLayoutComponent should be removed at this time. If addLayoutComponent is stubbed out, this method can be stubbed out as well.

 void removeLayoutComponent (Component comp) 

The following method is called by the container's getPreferredSize method to determine the size of the parent container. If you don't care about placing space around a component, call parent.getSize ().

 Dimension preferredLayoutSize (Container parent) 

The following method is called by the container's getMinimumSize method to determine the minimum size of the parent container. To determine this minimum size, you will typically call the getMinimumSize method of each component contained in the container. As with the preferredLayoutSize method, you can call parent.getSize ().

 Dimension minimumLayoutSize (Container parent) 

The following method is called when the parent container is displayed for the first time, and whenever this container is resized. It takes care of laying out parent 's components. To obtain these components, you can call parent 's getComponents method, or refer to previously saved components. Call each component's setBounds method to position and size the component (as long as it is visible).

 void layoutContainer (Container parent) 

Listing 14.26 presents source code to a debugging layout manager called DebugLayout. In addition to providing debugging messages (to show what is happening), this layout manager also attempts to lay out its components by assuming that the width and height of each component are the same.

Caution

This assumption leads to a technique that really needs to be improved, because the technique usually results in components along the right side and the bottom being partially hidden.


Listing 14.26 The DebugLayout Source Code
 // DebugLayout.java import java.awt.*; class DebugLayout implements LayoutManager {    public void addLayoutComponent (String name, Component comp)    {       System.out.println ("addLayoutComponent called");       System.out.println ("name = " + name);       System.out.println ("comp = " + comp);    }    public void removeLayoutComponent (Component comp)    {       System.out.println ("removeLayoutComponent called");       System.out.println ("comp = " + comp);    }    public Dimension preferredLayoutSize (Container parent)    {       System.out.println ("preferredLayoutSize called");       System.out.println ("parent = " + parent);       return parent.getSize ();    }    public Dimension minimumLayoutSize (Container parent)    {       System.out.println ("minimumLayoutSize called");       System.out.println ("parent = " + parent);       return parent.getSize ();    }    public void layoutContainer (Container parent)    {       System.out.println ("layoutContainer called");       System.out.println ("parent = " + parent);       Component [] c = parent.getComponents ();       if (c.length == 0)           return;       Dimension size = parent.getSize ();       Insets in = parent.getInsets ();       // Compute actual width and height by subtracting  parent's       // insets.       int width = size.width - in.left - in.right;       int height = size.height - in.top - in.bottom;       // Each component will be laid out as a square.       int cxy = (int) (Math.sqrt (width * height / c.length));       int x = in.left;       int y = in.top;       for (int i = 0; i < c.length; i++)       {            if (c [i].isVisible ())                c [i].setBounds (x, y, cxy, cxy);            x += cxy;            if (x >= width)            {                x = in.left;                y += cxy;            }       }    } } 

To see DebugLayout in action, Listing 14.27 presents source code to the UseDebugLayout application. This application sets a frame's layout manager to a debug layout manager and then adds 100 buttons to its container.

Listing 14.27 The UseDebugLayout Application Source Code
 // UseDebugLayout.java import java.awt.*; import java.awt.event.*; class UseDebugLayout extends Frame {    UseDebugLayout (String title)    {       super (title);       addWindowListener (new WindowAdapter ()                          {                              public void windowClosing (WindowEvent e)                              {                                 System.exit (0);                              }                          } );       setLayout (new DebugLayout ());       for (int i = 0; i < 100; i++)            add ("squished", new Button ("" + i));       setSize (200, 200);       setVisible (true);    }    public static void main (String [] args)    {       new UseDebugLayout ("Use Debug Layout");    } } 

AWT 1.1 introduced the LayoutManager2 interface to make up for shortcomings with LayoutManager. For example, LayoutManager2 provides an addLayoutComponent (Component comp, Object const) method that is called when a container's add (Component comp, Object const) method is called. As an exercise (for those so inclined), read up on LayoutManager2 and modify DebugLayout so it also implements this interface. Then, try calling add (Component comp, Object const) from UseDebugLayout instead of add (String name, Component comp).

   


Special Edition Using Java 2 Standard Edition
Special Edition Using Java 2, Standard Edition (Special Edition Using...)
ISBN: 0789724685
EAN: 2147483647
Year: 1999
Pages: 353

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net