Before you try to use a top-level container, you should read and understand Swing Components and the Containment Hierarchy. In particular, you should know these facts:
JFrame
,
JDialog
,
and JApplet
.
Note: Swing contains a fourth top-level container,JWindow
, which we don't cover because it isn't generally useful.JWindow
is the Swing version of the AWTWindow
class, which provides a window with no controls or title that is always on top of every other window.Swing also provides an intermediate container,
JInternalFrame
, that mimics a frame. However, internal frames aren't actually top-level containers.
|
|
TopLevelDemo.java
. Although the example uses a
JFrame
in a standalone application, the same concepts apply to
JApplet
s and JDialog
s.
Here's the containment hierarchy for this example's GUI:
As the ellipses imply, we left some details out of this diagram. We reveal the missing details a bit later. Here are the topics this section discusses:
Each program that uses Swing components has at least one top-level container. This top-level container is the root of a containment hierarchy -- the hierarchy that contains all of the Swing components that appear inside the top-level container.
As a rule, a standalone application with a Swing-based GUI has at least one
containment hierarchy with a JFrame
as its root. For example, if
an application has one main window and two dialogs, then the application has
three containment hierarchies, and thus three top-level containers. One
containment hierarchy has a JFrame
as its root, and each of the
other two has a JDialog
object as its root.
A Swing-based applet has at least one containment hierarchy, exactly one of
which is rooted by a JApplet
object. For example, an applet that
brings up a dialog has two containment hierarchies. The components in the
browser window are in a containment hierarchy rooted by a JApplet
object. The dialog has a containment hierarchy rooted by a
JDialog
object.
Here's the code that the preceding example uses to get a frame's content pane and add the yellow label to it:
As the code shows, you find the content pane of a top-level container by calling theframe.getContentPane().add(yellowLabel, BorderLayout.CENTER);
getContentPane
method. The default
content pane is a simple intermediate container that inherits from
JComponent
, and that uses a BorderLayout
as its
layout manager.
It's easy to customize the content pane -- setting the layout manager or
adding a border, for example. However, there is one tiny gotcha. The
getContentPane
method returns a Container
object,
not a JComponent
object. This means that if you want to take
advantage of the content pane's JComponent
features, you need to
either typecast the return value or create your own component to be the
content pane. Our examples generally take the second approach, since it's a
little cleaner. Another approach we sometimes take is to simply add a
customized component to the content pane, covering the content pane
completely.
If you create your own content pane, make sure it's opaque. A
JPanel
object makes a good content pane because it's simple and
it's opaque, by default. Note that the default layout manager for
JPanel
is FlowLayout
; you'll probably want to change
it. To make a component the content pane, use the top-level container's
setContentPane
method. For example:
JPanel contentPane = new JPanel(); contentPane.setLayout(new BorderLayout()); contentPane.setBorder(someBorder); contentPane.add(someComponent, BorderLayout.CENTER); contentPane.add(anotherComponent, BorderLayout.SOUTH); topLevelContainer.setContentPane(contentPane);
Note: Don't use non-opaque containers such asJScrollPane
,JSplitPane
, andJTabbedPane
as content panes. A non-opaque content pane results in messy repaints. Although you can make any Swing component opaque by invokingsetOpaque(true)
on it, some components don't look right when they're completely opaque. For example, tabbed panes generally let part of the underlying container show through, so that the tabs look non-rectangular. So an opaque tabbed pane just tends to look bad.
All top-level containers can, in theory, have a menu bar. In
practice, however, menu bars usually appear only in frames and perhaps in
applets. To add a menu bar to a frame or applet, you create a
JMenuBar
object, populate it with menus, and then call
setJMenuBar
. The TopLevelDemo
adds a menu bar to its
frame with this code:
For more information about implementing menus and menu bars, see How to Use Menus.frame.setJMenuBar(cyanMenuBar);
Each top-level container relies on a reclusive intermediate container called the root pane. The root pane manages the content pane and the menu bar, along with a couple of other containers. You generally don't need to know about root panes to use Swing components. However, if you ever need to intercept mouse clicks or paint over multiple components, you should get acquainted with root panes.
Here's a glimpse at the components that a root pane provides to a frame (and to every other top-level container):
For more information about the intricacies of root panes, see How to Use Root Panes.
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class TopLevelDemo { public static void main(String s[]) { JFrame frame = new JFrame("TopLevelDemo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JLabel yellowLabel = new JLabel(""); yellowLabel.setOpaque(true); yellowLabel.setBackground(Color.yellow); yellowLabel.setPreferredSize(new Dimension(200, 180)); JMenuBar cyanMenuBar = new JMenuBar(); cyanMenuBar.setOpaque(true); cyanMenuBar.setBackground(Color.cyan); cyanMenuBar.setPreferredSize(new Dimension(200, 20)); frame.setJMenuBar(cyanMenuBar); frame.getContentPane().add(yellowLabel, BorderLayout.CENTER); frame.pack(); frame.setVisible(true); } }