Containers
Contents:
Container
Panel
Insets
Window
Frames
Dialogs
FileDialog
This chapter covers a special type of Component
called Container
. A Container
is a subclass of Component
that can contain other components, including other containers. Container
allows you to create groupings of objects on the screen. This chapter covers the methods in the Container
class and its subclasses: Panel
, Window
, Frame
, Dialog
, and FileDialog
. It also covers the Insets
class, which provides an internal border area for the Container
classes.
Every container has a layout associated with it that controls how the container organizes the components in it. The layouts are described in Layouts.
Java 1.1 introduces a special Container
called ScrollPane
. Because of the similarities between scrolling and ScrollPane
, the new ScrollPane
container is covered with the Scrollbar
class in Scrolling.
Container
Container
is an abstract class that serves as a general purpose holder of other Component
objects. The Container
class holds the methods for grouping the components together, laying out the components inside it, and dealing with events occurring within it. Because Container
is an abstract class, you never see a pure Container
object; you only see subclasses that add specific behaviors to a generic container.
Container Methods
ConstructorsThe abstract Container
class contains a single constructor to be called by its children. Prior to Java 1.1, the constructor was package private.
- protected Container()
- The constructor for
Container
creates a new component without a native peer. Since you no longer have a native peer, you must rely on your container to provide a display area. This allows you to create containers that require fewer system resources. For example, if you are creating panels purely for layout management, you might consider creating aLightweightPanel
class to let you assign a layout manager to a component group. UsingLightweightPanel
will speed things up since events do not have to propagate through the panel and you do not have to get a peer from the native environment. The following code creates theLightweightPanel
class:import java.awt.*; public class LightweightPanel extends Container { LightweightPanel () {} LightweightPanel (LayoutManager lm) { setLayout(lm); } }
A Container
holds a set of objects within itself. This set of methods describes how to examine and add components to the set.
- public int getComponentCount ()
public int countComponents () - The
getComponentCount()
method returns the number of components within the container at this level.getComponentCount()
does not count components in any childContainer
(i.e., containers within the current container).countComponents()
is the Java 1.0 name for this method. - public Component getComponent (int position)
- The
getComponent()
method returns the component at the specificposition
within it. Ifposition
is invalid, this method throws the run-time exceptionArrayIndexOutOfBoundsException
. - public Component[] getComponents ()
getComponents()
returns an array of all the components held within the container. Since these are references to the actual objects on the screen, any changes made to the components returned will be reflected on the display.- public Component add (Component component, int position)
- The
add()
method addscomponent
to the container atposition
. Ifposition
is -1,add()
insertscomponent
as the last object within the container. What the container does withposition
depends upon theLayoutManager
of the container. Ifposition
is invalid, theadd()
method throws the run-time exceptionIllegalArgumentException
. If you try to addcomponent
's container to itself (anywhere in the containment tree), this method throws anIllegalArgumentException
. In Java 1.1, if you try to add aWindow
to a container,add()
throws the run-time exceptionIllegalArgumentException
. If you try to addcomponent
to a container that already contains it, the container is removed and re-added, probably at a different position.Assuming that nothing goes wrong, the parent of
component
is set to the container, and the container is invalidated.add()
returns thecomponent
just added.Calling this method generates a
ContainerEvent
with the idCOMPONENT_ADDED
. - public Component add (Component component)
- The
add()
method addscomponent
to the container as the last object within the container. This is done by calling the earlier version ofadd()
with aposition
of -1. If you try to addcomponent
's container to itself (anywhere in the containment tree), this method throws the run-time exceptionIllegalArgumentException
. In Java 1.1, if you try to add aWindow
to a container,add()
throws the run-time exceptionIllegalArgumentException
.Calling this method generates a
ContainerEvent
with the idCOMPONENT_ADDED
. - public void add (Component component, Object constraints)
public Component add (String name, Component component) - This next version of
add()
is necessary for layouts that require additional information in order to place components. The additional information is provided by theconstraints
parameter. This version of theadd()
method calls theaddLayoutComponent()
method of theLayoutManager
. What the container does withconstraints
depends upon the actualLayoutManager
. It can be used for naming containers within aCardLayout
, specifying a screen area forBorderLayout
, or providing a set ofGridBagConstraints
for aGridBagLayout
. In the event that thisadd()
is called and the currentLayoutManager
does not take advantage ofconstraints
,component
is added at the end with a position of -1. If you try to addcomponent
's container to itself (anywhere in the containment tree), this method throws the run-time exceptionIllegalArgumentException
. In Java 1.1, if you try to add aWindow
to a container,add()
throws the run-time exceptionIllegalArgumentException
.The
add(String
,Component)
method was changed toadd(component, object)
in Java 1.1 to accommodate theLayoutManager2
interface (discussed in Layouts) and to provide greater flexibility. In all cases, you can just flip the parameters to bring the code up to 1.1 specs. The string used as an identifier in Java 1.0 is just treated as a particular kind of constraint.Calling this method generates a
ContainerEvent
with the idCOMPONENT_ADDED
. - public void add (Component component, Object constraints, int index)
- This final version of
add()
is necessary for layouts that require anindex
and need additional information to place components. The additional information is provided by theconstraints
parameter. This version ofadd()
also calls theaddLayoutComponent()
method of theLayoutManager
.component
is added with a position ofindex
. If you try to addcomponent
's container to itself (anywhere in the containment tree), this method throws the run-time exceptionIllegalArgumentException
. In Java 1.1, if you try to add aWindow
to aContainer
,add()
throws the run-time exceptionIllegalArgumentException
.Some layout managers ignore any index. For example, if you call
add(aButton, BorderLayout.NORTH, 3)
to add aButton
to aBorderLayout
panel, theButton
appears in the north region of the layout, no matter what the index.Calling this method generates a
ContainerEvent
with the idCOMPONENT_ADDED
. - protected void addImpl(Component comp, Object constraints, int index)
- The protected
addImpl()
method is the helper method that all the others call. It deals with synchronization and enforces all the restrictions on adding components to containers.The
addImpl()
method tracks the container's components in an internal list. The index with which each component is added determines its position in the list. The lower the component's index, the higher it appears in the stacking order. In turn, the stacking order determines how components are displayed when sufficient space isn't available to display all of them. Components that are added without indices are placed at the end of the list (i.e., at the end of the stacking order) and therefore displayed behind other components. If all components are added without indices, the first component added to the container is first in the stacking order and therefore displayed in front.You could override
addImpl()
to track when components are added to a container. However, the proper way to find out when components are added is to register aContainerListener
and watch for theCOMPONENT_ADDED
and theCOMPONENT_REMOVED
events. - public void remove (int index)
- The
remove()
method deletes thecomponent
at positionindex
from the container. Ifindex
is invalid, theremove()
method throws the run-time exceptionIllegalArgumentException
. This method calls theremoveLayoutComponent()
method of the container'sLayoutManager
.removeAll()
generates aContainerEvent
with the idCOMPONENT_REMOVED
. - public void remove (Component component)
- The
remove()
method deletescomponent
from the container, if the container directly containscomponent
.remove()
does not look through nested containers trying to findcomponent
. This method calls theremoveLayoutComponent()
method of the container'sLayoutManager
.When you call this method, it generates a
ContainerEvent
with the idCOMPONENT_REMOVED
. - public void removeAll ()
- The
removeAll()
method removes all components from the container. This is done by looping through all the components, setting each component's parent tonull
, setting the container's reference to the component tonull
, and invalidating the container.When you call this method, it generates a
ContainerEvent
with the idCOMPONENT_REMOVED
for each component removed. - public boolean isAncestorOf(Component component)
- The
isAncestorOf()
method checks to see ifcomponent
is a parent (or grandparent or great grandparent) of this container. It could be used as a helper method foraddImpl()
but is not. Ifcomponent
is an ancestor of the container,isAncestorOf()
returnstrue
; otherwise, it returnsfalse
.
Every container has a LayoutManager
. The LayoutManager
is responsible for positioning the components inside the container. The Container
methods listed here are used in sizing the objects within the container and specifying a layout.
- public LayoutManager getLayout ()
- The
getLayout()
method returns the container's currentLayoutManager
. - public void setLayout (LayoutManager manager)
- The
setLayout()
method changes the container'sLayoutManager
tomanager
and invalidates the container. This causes the components contained inside to be repositioned based uponmanager
's rules. Ifmanager
isnull
, there is no layout manager, and you are responsible for controlling the size and position of all the components within the container yourself. - public Dimension getPreferredSize ()
public Dimension preferredSize () - The
getPreferredSize()
method returns theDimension
(width
andheight
) for the preferred size of the components within the container. The container determines its preferred size by calling thepreferredLayoutSize()
method of the currentLayoutManager
, which says how much space the layout manager needs to arrange the components. If you override this method, you are overriding the default preferred size.preferredSize()
is the Java 1.0 name for this method. - public Dimension getMinimumSize ()
public Dimension minimumSize () - The
getMinimumSize()
method returns the minimumDimension
(width
andheight
) for the size of the components within the container. This container determines its minimum size by calling theminimumLayoutSize()
method of the currentLayoutManager
, which computes the minimum amount of space the layout manager needs to arrange the components. It is possible forgetMinimumSize()
andgetPreferredSize()
to return the same dimensions. There is no guarantee that you will get this amount of space for the layout.minimumSize()
is the Java 1.0 name for this method. - public Dimension getMaximumSize ()
- The
getMaximumSize()
method returns the maximumDimension
(width
andheight
) for the size of the components within the container. This container determines its maximum size by calling themaximumLayoutSize()
method of the currentLayoutManager2
, which computes the maximum amount of space the layout manager needs to arrange the components. If the layout manager is not an instance ofLayoutManager2
, this method calls thegetMaximumSize()
method of theComponent
, which returnsInteger.MAX_VALUE
for both dimensions. None of thejava.awt
layout managers use the concept of maximum size yet. - public float getAlignmentX ()
- The
getAlignmentX()
method returns the alignment of the components within the container along the x axis. This container determines its alignment by calling the currentLayoutManager2
'sgetLayoutAlignmentX()
method, which computes it based upon its children. The return value is between 0.0 and 1.0. Values nearer 0 indicate that the component should be placed closer to the left edge of the area available. Values nearer 1 indicate that the component should be placed closer to the right. The value 0.5 means the component should be centered. If the layout manager is not an instance ofLayoutManager2
, this method callsComponent
'sgetAlignmentX()
method, which returns the constantComponent.CENTER_ALIGNMENT
. None of thejava.awt
layout managers use the concept of alignment yet. - public float getAlignmentY ()
- The
getAlignmentY()
method returns the alignment of the components within the container along the y axis. This container determines its alignment by calling the currentLayoutManager2
'sgetLayoutAlignmentY()
method, which computes it based upon its children. The return value is between 0.0 and 1.0. Values nearer 0 indicate that the component should be placed closer to the top of the area available. Values nearer 1 indicate that the component should be placed closer to the bottom. The value 0.5 means the component should be centered. If the layout manager is not an instance ofLayoutManager2
, this method callsComponent
'sgetAlignmentY()
method, which returns the constantComponent.CENTER_ALIGNMENT
. None of thejava.awt
layout managers use the concept of alignment yet. - public void doLayout ()
public void layout () - The
doLayout()
method ofContainer
instructs theLayoutManager
to lay out the container. This is done by calling thelayoutContainer()
method of the currentLayoutManager
.layout()
is the Java 1.0 name for this method. - public void validate ()
- The
validate()
method sets the container's valid state totrue
and recursively validates all of its children. If a child is aContainer
, its children are in turn validated. Some components are not completely initialized until they are validated. For example, you cannot ask aButton
for its display dimensions or position until it is validated. - protected void validateTree ()
- The
validateTree()
method is a helper forvalidate()
that does all the work. - public void invalidate ()
- The
invalidate()
method invalidates the container and recursively invalidates the children. If the layout manager is an instance ofLayoutManager2
, itsinvalidateLayout()
method is called to invalidate any cached values.
The event model for Java is described in Events. These methods help in the handling of the various system events at the container level.
- public void deliverEvent (Event e)
- The
deliverEvent()
method is called by the system when the Java 1.0Event
e
happens.deliverEvent()
tries to locate a component contained in the container that should receive it. If one is found, the x and y coordinates ofe
are translated for the new target, andEvent
e
is delivered to this by calling itsdeliverEvent()
. IfgetComponentAt()
fails to find an appropriate target, the event is just posted to the container withpostEvent()
. - public Component getComponentAt (int x, int y)
public Component locate (int x, int y) - The container's
getComponentAt()
method calls each component'scontains()
method to see if thex
andy
coordinates are within it. If they are, that component is returned. If the coordinates are not in any child component of this container, the container is returned. It is possible forgetComponentAt()
to returnnull
if thex
andy
coordinates are not within the container. The methodgetComponentAt()
can return anotherContainer
or a lightweight component.locate()
is the Java 1.0 name for this method. - public Component getComponentAt (Point p)
- This
getComponentAt()
method is identical to the previous method, with the exception that the location is passed as a single point, rather than as separatex
andy
coordinates.
With the 1.1 event model, you register listeners, which are told when events occur. Container events occur when a component is added or removed.
- public synchronized void addContainerListener(ContainerListener listener)
- The
addContainerListener()
method registerslistener
as an object interested in receiving notifications when anContainerEvent
passes through theEventQueue
with thisContainer
as its target. Thelistener.componentAdded()
orlistener.componentRemoved()
method is called when these events occur. Multiple listeners can be registered. The following code demonstrates how to use aContainerListener
to register action listeners for all buttons added to an applet. It is similar to theButtonTest11
example in Button Events. The trick that makes this code work is the call toenableEvents()
ininit()
. This method makes sure that container events are delivered in the absence of listeners. In this applet, we know there won't be any container listeners, so we must enable container events explicitly before adding any components.
// Java 1.1 only import java.awt.*; import java.applet.*; import java.awt.event.*; public class NewButtonTest11 extends Applet implements ActionListener { Button b; public void init () { enableEvents (AWTEvent.CONTAINER_EVENT_MASK); add (b = new Button ("One")); add (b = new Button ("Two")); add (b = new Button ("Three")); add (b = new Button ("Four")); } protected void processContainerEvent (ContainerEvent e) { if (e.getID() == ContainerEvent.COMPONENT_ADDED) { if (e.getChild() instanceof Button) { Button b = (Button)e.getChild(); b.addActionListener (this); } } } public void actionPerformed (ActionEvent e) { System.out.println ("Selected: " + e.getActionCommand()); } }
- public void removeContainerListener(ContainerListener listener)
- The
removeContainerListener()
method removeslistener
as an interested listener. Iflistener
is not registered, nothing happens. - protected void processEvent(AWTEvent e)
- The
processEvent()
method receives allAWTEvent
s with thisContainer
as its target.processEvent()
then passes them along to any listeners for processing. When you subclassContainer
, overridingprocessEvent()
allows you to process all events yourself, before sending them to any listeners. There is no equivalent under the 1.0 event model.If you override
processEvent()
, remember to callsuper.processEvent(e)
last to ensure that regular event processing can occur. If you want to process your own events, it's a good idea to callenableEvents()
(inherited fromComponent
) to ensure that events are delivered even in the absence of registered listeners. - protected void processContainerEvent(ContainerEvent e)
- The
processContainerEvent()
method receives allContainerEvent
s with thisContainer
as its target.processContainerEvent()
then passes them along to any listeners for processing. When you subclassContainer
, overriding theprocessContainerEvent()
method allows you to process all container events yourself, before sending them to any listeners. There is no equivalent under the 1.0 event model.If you override the
processContainerEvent()
method, remember to callsuper.processContainerEvent(e)
last to ensure that regular event processing can occur. If you want to process your own events, it's a good idea to callenableEvents()
(inherited fromComponent
) to ensure that events are delivered even in the absence of registered listeners.
The following methods are early vestiges of an approach to painting and printing. They are not responsible for anything that couldn't be done with a call to paintAll()
or printAll()
. However, they are available if you wish to call them.
- public void paintComponents (Graphics g)
- The
paintComponents()
method ofContainer
paints the different components it contains. It calls each component'spaintAll()
method with a clipped graphics contextg
, which is eventually passed topaint()
. - public void printComponents (Graphics g)
- The
printComponents()
method ofContainer
prints the different components it contains. It calls each component'sprintAll()
method with a clipped graphics contextg
, which is passed toprint()
, and eventually works its way topaint()
.
Since it is the container's responsibility to deal with painting lightweight peers, the paint()
and print()
methods are overridden in Java 1.1.
- public void paint(Graphics g)
- The
paint()
method ofContainer
paints the different lightweight components it contains.
- public void print(Graphics g)
- The
print()
method ofContainer
prints the different lightweight components it contains.
NOTE:
If you override paint()
or print()
in your containers (especially applets), call super.paint(g)
or super.print(g)
, respectively, to make sure that lightweight components are rendered. This is a good practice even if you don't currently use any lightweight components; you don't want your code to break mysteriously if you add a lightweight component later.Peers
The container is responsible for creating and destroying all the peers of the components within it.
- public void addNotify ()
- The
addNotify()
method ofContainer
creates the peer of all the components within it. AfteraddNotify()
is called, theContainer
is invalid. It is useful for top-level containers to call this method explicitly before calling the methodsetVisible(true)
to guarantee that the container is laid out before it is displayed. - public void removeNotify ()
- The
removeNotify()
method destroys the peer of all the top-level objects contained within it. This in effect destroys the peers of all the components within the container.
- protected String paramString ()
- When you call the
toString()
method of a container, the defaulttoString()
method ofComponent
is called. This in turn callsparamString()
which builds up the string to display. At theContainer
level,paramString()
appends the layout manager name, likelayout=java.awt.BorderLayout
, to the output. - public Insets getInsets ()
public Insets insets () - The
getInsets()
method gets the container's current insets. An inset is the amount of space reserved for the container to use between its edge and the area actually available to hold components. For example, in aFrame
, the inset for the top would be the space required for the title bar and menu bar. Insets exist for top, bottom, right, and left. When you override this method, you are providing an area within the container that is reserved for free space. If the container has insets, they would be the default. If not, the default values are all zeroes.The following code shows how to override
insets()
to provide values other than the default. The top and bottom have 20 pixels of inset. The left and right have 50. Insets describes theInsets
class in more detail.public Insets insets () { // getInsets() for Java 1.1 return new Insets (20, 50, 20, 50); }
To find out the current value, just call the method and look at the results. For instance, for a
Frame
the results could be the following in the format used bytoString()
:java.awt.Insets[top=42,left=4,right=4,bottom=4]
The
42
is the space required for the title and menu bar, while the4
around the edges are for the window decorations. These results are platform specific and allow you to position items based upon the user's run-time environment.When drawing directly onto the graphics context of a container with a large inset such as
Frame
, remember to work around the insets. If you do something likeg.drawString("Hello World", 5, 5)
onto aFrame
, the user won't see the text. It will be under the title bar and menu bar.insets()
is the Java 1.0 name for this method. - public void list (PrintWriter output, int indentation)
public void list (PrintStream output, int indentation) - The
list()
method is very helpful if you need to find out what is inside a container. It recursively calls itself for each container level of objects inside it, increasing theindentation
at each level. The results are written to thePrintStream
orPrintWriter
output
.