[Chapter 15] 15.2 The Peer Interfaces

#

| Chapter 15 Toolkit and Peers |

## 15.2 The Peer Interfaces

Each GUI component that AWT provides has a peer. The peer is the implementation of that component in the native environment. For example, the `Choice` component in AWT corresponds to some native object that lets the user select one or more items from a list. As a Java developer, you need to worry only about the interface of the `Choice` object; when someone runs your program, the `Choice` object is mapped to an appropriate native object, which is the `Choice` peer, that "does the right thing." You don't really care what the peer is or how it's implemented; in fact, the peer may look (and to some extent, behave) differently on each platform.

The glue that allows an AWT component and its peer to work together is called a peer interface. A peer interface is simply an interface that defines the methods that the peer is required to support. These interfaces are collected in the package `java.awt.peer`. For example, this package contains the `ButtonPeer` interface, which contains the single method `setLabel()`. This means that the native object used to implement a `Button` must contain a method called `setLabel()` in order for AWT to use it as a button peer. (It's not quite that simple; since a button is also a `Component`, the button's peer must also implement the `ComponentPeer` interface, which is much more complicated.)

With one exception, there is a one-to-one correspondence between `Component` classes and peer interfaces: a `Window` has a `WindowPeer`, a `Checkbox` has a `CheckboxPeer`, and so on. The one exception is a new peer interface that appears in Java 1.1: the `LightweightPeer`, which doesn't have a corresponding component. The `LightweightPeer` is used by components that exist purely in Java, don't have a native peer, and are displayed and managed by another container. `LightweightPeer` makes it easier to create new components or containers that can behave like other components, but don't subclass `Canvas` or `Panel` and don't correspond to anything in the native environment. The best usage I can think of is to subclass `Container` to create a lightweight `Panel`. If you are only using a `Panel` to manage layout, there is no need for a peer to be created to process events. This should result in substantial resource savings where multiple panels need to be created just to help with layout. The following code is all you need to create a `LightWeightPanel`:

    import java.awt.*;
    public class LightWeightPanel extends Container {
    }

There also tends to be a one-to-one relationship between the peer methods and the methods of the Java component. That is, each method in the peer interface corresponds to a method of the component. However, although a peer must implement each method in its peer interface, it doesn't necessarily have to do anything in that method. It's entirely possible for a platform to have a native button object that doesn't let you set the label. In this case, the button peer would implement the `setLabel()` method required by the `ButtonPeer` interface, but it wouldn't do anything. Of course, the component may also have many methods that don't correspond to the peer methods. Methods that don't correspond to anything in the peer are handled entirely within Java.

The `ComponentPeer` interface is the parent of all non-menu objects in the peer package. The `MenuComponentPeer` is the parent of all menu objects. The trees mirror the regular object hierarchies. Figure 15.1 shows the object hierarchy diagram.

#### Figure 15.1: java.awt.peer object hierarchy

Creating a Java component (e.g., `Button b = new Button (`Foo`)`) does not create the peer. An object's peer is created when the object's `addNotify()` method is called. This is usually when the component's container is added to the screen. The call to a component's `addNotify()` method in turn calls the appropriate `createxxxx()` method of the `Toolkit` (for a Button, `createButton()`). Figure 15.2 shows the process.

#### Figure 15.2: Creating a Button peer

When you remove a component from a container by calling `remove()`, the container calls the component's `removeNotify()` method. This usually results in a call to the peer's `dispose()` method. Depending on the particular component, `removeNotify()` may be overridden to perform additional work. Removing a `Component` from a `Container` does not destroy the `Component`. The next time the method `addNotify()` is called, the component must be recreated by the peer, with its previous characteristics. For instance, when a `TextField` is removed, the current text, plus the start and stop points for the current selection, are saved. These will be restored if you add the text field to its container again. For some components, like a `Label`, there is no need to retain any additional information.

A component's peer needs to exist only when the user is interacting with it. If you are developing resource-intensive programs, you might want to consider drawing the components manually when they do not have the focus and using the peer only when they actually have input focus. This technique can save a considerable amount of memory resources but requires extra work on your part as a developer and goes beyond the scope of this book. The `LightweightPeer` interface appears to be designed to make this process easier: you could create a dummy button that doesn't do anything and uses the `LightweightPeer`. Whenever the mouse enters the button's space, you could quickly remove the dummy button and add a real button.

The peer interfaces are listed in their entirety in the reference section. We won't list them here, primarily because you don't need to worry about them unless you're porting Java to a new platform. Each method in a peer interface corresponds exactly to the similarly named method in the matching component. `LightweightPeer` is the only exception, because it doesn't have a matching component, but that's easy to take care of: as you'd expect, `LightweightPeer` doesn't define any methods. (Of course, a peer that implements `LightweightPeer` would still need to implement the methods inherited from `ComponentPeer`, but those are inherited when you subclass `Component`.)

Toolkit |  | Data Transfer