Card 05/ 08

ExampleDifficulty: Intermediate2 min

Composite in the Wild: Java Swing's Container

A panel holds buttons and other panels, and painting the window paints them all.

Java's Swing toolkit builds every window as a Composite. Every widget extends java.awt.Component, and java.awt.Container, a component that holds components, is the composite. A JPanel is a container, so a panel can hold buttons, labels and other panels, and the toolkit paints or lays out a window by asking the top container, which asks its children.

java
import java.awt.Component;
import java.awt.Container;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class CoSwing {
    static int count(Component component) {
        int total = 1;
        if (component instanceof Container container) {
            for (Component child : container.getComponents()) {
                total += count(child);
            }
        }
        return total;
    }

    static void print(Component component, String indent) {
        System.out.println(indent + component.getClass().getSimpleName());
        if (component instanceof Container container) {
            for (Component child : container.getComponents()) {
                print(child, indent + "  ");
            }
        }
    }

    public static void main(String[] args) {
        JPanel buttons = new JPanel();
        buttons.add(new JButton("Save"));
        buttons.add(new JButton("Cancel"));

        JPanel form = new JPanel();
        form.add(new JLabel("Name"));
        form.add(buttons);

        print(form, "");
        System.out.println("components: " + count(form));
        System.out.println("JButton is a Container: " + (new JButton() instanceof Container));
    }
}
OutputRan with eclipse-temurin:21-jdk (Java 21.0.12)
JPanel
  JLabel
  JPanel
    JButton
    JButton
components: 5
JButton is a Container: true
`getComponents` returns a container's children, and both functions recurse through them.

The listing builds a form holding a label and a panel of two buttons, with no window shown, and walks it twice: once to print the tree and once to count its nodes. It ran with java.awt.headless=true in eclipse-temurin:21-jdk, which allows building components but not displaying them. Both walks are five lines long because they treat every node as a Component and look inside only the ones that are containers.

The last line shows that a JButton is a Container too. Swing's JComponent extends Container, so every Swing widget can technically hold children, which is the transparent choice of where to declare add. The browser's DOM has the same shape: an element is a node, it holds nodes, and the browser renders a page by walking that tree.