Nested Containers and The Event Chain
When I create compound components, how is event handling affected and how can the constituent components communicate with components in the applet or other containers? Consider using the KeyPad to flip through a set of "slides." The main applet will have a KeyPad and a SlideViewer that are laid out next to each other with the default FlowLayout. The SlideViewer will be a compound Component containing a series of slides laid out using CardLayout. Here is the running SlideShow applet:
How can you get the key pad to flip through the slides in the CardLayout? Define an interface called KeyPadObserver that allows an object to be notified when a key has been pressed:
interface KeyPadObserver {
public void pressed(String key);
}
The interface allows the key pad to be more general. An arbitrary object that implements this interface can then be attached to a new version of the KeyPad called KeyPadWithObserver:
class KeyPadWithObserver extends Panel {
String[] keys = { "1","2","3",
"4","5","6",
"7","8","9",
"*","0","#" };
Button[] b = new Button[keys.length];
KeyPadObserver observer;
public KeyPadWithObserver(KeyPadObserver o) {
observer = o;
setLayout(new GridLayout(4,3));
for (int i=0; i<keys.length; i++) {
b[i] = new Button(String.valueOf(keys[i]));
add(b[i]);
}
}
public boolean action(Event e, Object arg) {
observer.pressed((String)arg);
return true;
}
}
A KeyPadObserver is passed to KeyPadWithObserver during construction. Then, upon key press (the action method is called), a KeyPadWithObserver can notify the observer. Events generated by a key are handled in KeyPadWithObserver rather than handling them in the SlideShow applet. The following containment hierarchy demonstrates the event chain when the "2" Button on the KeyPadWithObserver is pushed:
The SlideViewer is nothing but a Panel managed by CardLayout that implements
the KeyPadObserver interface. The SlideViewer is designed so that the slides
can be specified as an array of arbitrary Component objects:
class SlideViewer extends Panel implements KeyPadObserver {
CardLayout layout;
public SlideViewer(Component[] comps) {
layout = new CardLayout();
setLayout(layout);
for (int i=0; i<comps.length; i++) {
// set the key of component to the index
add(String.valueOf(i+1), comps[i]);
}
}
public void pressed(String key) {
layout.show(this, key);
}
}
The pressed method is called by the KeyPadWithObserver object when a key is pressed via:
observer.pressed((String)arg);
When the KeyPadWithOberserver object is created by the SlideShow applet, the SlideViewer is passed as the KeyPadObserver. SlideShow does nothing but create a set of slides, a SlideViewer, and a KeyPadWithObserver that is attached to the SlideViewer.
import java.awt.*;
import java.applet.Applet;
public class SlideShow extends Applet {
Component[] slides = { new Label("Slide 1"),
new Button("Slide 2"),
new TextField("Slide 3"),
new TextField("Slide 4"),
new Label("Slide 5"),
new Label("Slide 6"),
new Label("Slide 7"),
new Label("Slide 8"),
new Label("Slide 9") };
public void init() {
SlideViewer sv = new SlideViewer(slides);
KeyPadWithObserver keypad = new KeyPadWithObserver(sv);
add(keypad);
add(sv);
}
}
Note that there only 9 slides. Buttons "*", "0", and "#" will not affect the SlideViewer.
Related Magercise(s):