0% found this document useful (0 votes)
266 views

Trail

The document discusses the Java Foundation Classes (JFC) and Swing API. It notes that JFC includes GUI components, pluggable look-and-feel support, accessibility APIs, Java 2D APIs, and drag-and-drop support. Swing was the code name for the project that developed new GUI components for JFC. The Swing API has been included since Java 2 platform version 1.2 and provides reusable GUI components like buttons, text fields, tables and more. It also allows programs to have different looks and feels.

Uploaded by

Mad Madhavi
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
266 views

Trail

The document discusses the Java Foundation Classes (JFC) and Swing API. It notes that JFC includes GUI components, pluggable look-and-feel support, accessibility APIs, Java 2D APIs, and drag-and-drop support. Swing was the code name for the project that developed new GUI components for JFC. The Swing API has been included since Java 2 platform version 1.2 and provides reusable GUI components like buttons, text fields, tables and more. It also allows programs to have different looks and feels.

Uploaded by

Mad Madhavi
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 148

About the JFC and Swing

JFC is short for Java Foundation Classes, which encompass a group of features for building graphical user interfaces (GUIs1) and adding rich graphics functionality and interactivity to Java applications. JFC was first announced at the 1997 JavaOneSM developer conference. It is defined as containing the features shown in Table 1.2

Table 1. Features of the Java Foundation Classes


Feature Swing GUI Components Pluggable Look-andFeel Support Description Includes everything from buttons to split panes to tables. See screenshots of all the components in A Visual Index to Swing Components (page 37) in Chapter 3. Gives any program that uses Swing components a choice of look and feel. For example, the same program can use either the Java or the Windows look and feel. Many more look-and-feel packages are available from various sources. As of v1.4.2, the Java platform supports the GTK+ look and feel, which makes hundreds of existing look and feels available to Swing programs. Enables assistive technologies, such as screen readers and Braille displays, to get information from the user interface. Enables developers to easily incorporate high-quality 2D graphics, text, and images in applications and applets. Java 2D includes extensive APIs for generating and sending high-quality output to printing devices. Provides the ability to drag and drop between Java applications and native applications. Allows developers to build applications that can interact with users worldwide in their own languages and cultural conventions. With the input method framework developers can build applications that accept text in languages that use thousands of different characters, such as Japanese, Chinese, or Korean.

Accessibility API Java 2DTM API

Drag-and-Drop Support Internationalization

This book concentrates on the Swing components. We help you choose the appropriate components for your GUI, tell you how to use them, and give you the background information you need to use them effectively. We also discuss other JFC features as they apply to Swing components. "Swing" was the code name of the project that developed the new components. Although unofficial, it's frequently used to refer to the new components and related API. "Swing" is immortalized in the package names for the Swing API, which begin with j .a

Which Releases Contain the Swing API?


The short answer is that the Swing API has been included in the Java 2 platform, Standard Edition (J2SETM) since its initial release (1.2). A 1.4.2 release of the Java 2 platform is included on the CD that accompanies this book. You can also download the latest release from the Sun Microsystems Web site at: http://java.sun.com/j2se/. This book concentrates on the Swing API in the Java 2 platform, Standard Edition, v1.4.2. Except where noted, the code in this book works, without change, with earlier J2SE releases.3 We also include notes about a few important changes expected in 1.5.

Which Swing Packages Should I Use?


The Swing API is powerful, flexibleand immense. In release 1.4 of the Java platform, the Swing API has 17 public packages:

Fortunately, most programs use only a small subset of the API. This book sorts out the API for you, giving you examples of common code and pointing you to methods and classes you're likely to need. Most of the code in this book uses only one or two Swing packages:

j a j (not always required) a

In this sample chapter, you'll get a brief introduction to using the Java Foundation Classes (JFC) Swing packages, you'll find out how to get your hands on the right software, and you'll be walked through the process of compiling and running a program that uses the Swing packages.

Compiling and Running Swing Programs


This section explains how to compile and run a Swing application. The compilation instructions work for all Swing programsapplets, as well as applications. The following are the steps you need to follow: 1. 2. 3. 4. Install the latest release of the Java 2 platform, if you haven't already done so. Create a program that uses Swing components. Compile the program. Run the program.

If you're new to writing and compiling programs that use the Java platform, read The Java Tutorial trail "Getting Started" first; it's available online and on the CD at: JavaTutorial/getStarted/index.html. That trail also explains common errors that users may encounter.

Install the Latest Release of the Java 2 Platform


You can download the latest release of the J2SE SDK for free from http://java.sun.com/j2se. Version 1.4.2 of the J2SE SDK is included on the CD that accompanies this book.

Create a Program That Uses Swing Components


You can use a simple program we provide, called Hthat brings up the GUI shown ,e in Figure 1. The program is in a single file, He .4 When you save this file, you must

match the spelling and capitalization of its name exactly. If you prefer to type in the file's code yourself, you can find the full code starting on page 12 in Chapter 2. Figure 1. The HelloWorldSwing application.

Compile the Program


Your next step is to compile the program. Here's an example of compiling He lloWorldSwing.jav : javac HelloWorldSwing.java If you can't compile, make sure you're using the compiler in a recent release of the Java platform, such as 1.4.2 included on this book's CD. Once you've updated your SDK, you should be able to use the programs in this book without changes. Another common mistake is installing the Java Runtime Environment (JRE) and not the full Software Development Kit (SDK) needed to compile these programs. Refer to the "Getting Started" trail of The Java Tutorial to help you solve any compiling problems you encounter.5 Another installation troubleshooting guide for the Java 2 platform is online at: http://servlet.java.sun.com/help/installation/.

Run the Program


After you compile the program successfully, you can run it. Assuming that your program uses a standard look and feelsuch as the Java, Windows, or GTK+ look and feelyou can use the interpreter to run the program without adding anything to your class path. For example: java HelloWorldSwing For programs that use a nonstandard look and feel or any other nonstandard code package, you must make sure that the necessary classes are in the class path. For example:

Solaris
java -classpath.:/home/me/lnfdir/newlnf.jar HelloWorldSwing

Microsoft Windows
java -classpath .;C:\java\lnfdir\newlnf.jar HelloWorldSwing Alternatively, you can launch your program from a Web browser using Java Web Start.

Running Programs Using Java Web Start


Java Web Start is a technology that simplifies the distribution of applications. With a click on a Web page link, you can launch full-featured applications without a complicated download and installation process. The first time you launch an application, Java Web Start automatically downloads all necessary files. It then caches them on your computer so the application can be quickly relaunched from a desktop shortcut or from a Web browser. Java Web Start checks for updates each time you run a remote application and downloads any updated files automatically. In 1.4.1 and later releases of the Java platform, Java Web Start is shipped as part of the platform. So, if you have J2SE or JRE v1.4.1 or higher, you already have Java Web Start installed. When you install a version of the Java platform with Java Web Start, on most platforms you'll see a Java Web Start shortcut on your desktop. (See Figure 2.)

Figure 2. The Java Web Start desktop shortcut. To test whether your browser can launch an application using Java Web Start, point it to one of the following places and click the "Launch JavaTM Web Start" link:

JavaTutorial/tutorial/uiswing/14start/HelloJWS.html (on this book's CD) http://java.sun.com/docs/books/tutorial/uiswing/14start/HelloJWS.html

You should see a Java Web Start splash screen. (See Figure 3.) Figure 3. The Java Web Start splash screen. The application is then downloaded, and you should see what's shown in Figure 4. Figure 4. The HelloJWSYou can find the HelloJWS.java JavaTutorial/uiswing/14start/example1dot4/index.html#HelloJWS. application launched from a using Java Web Start.

source files here: Web browser

What Are the JFC and Swing?


JFC is short for Java Foundation Classes, which encompass a group of features to help people build graphical user interfaces (GUIs). The JFC was first announced at the 1997 JavaOne developer conference and is defined as containing the following features: The Swing Components Include everything from buttons to split panes to tables. You can see mugshots of all the components in A Visual Index to the Swing Components . Pluggable Look and Feel Support Gives any program that uses Swing components a choice of looks and feels. For example, the same program can use either the Java look and feel or the Windows look and feel. We expect many more look-and-feel packages -- including some that use sound instead of a visual "look" -- to become available from various sources. Accessibility API Enables assistive technologies such as screen readers and Braille displays to get information from the user interface. Java 2D API (Java 2 Platform only) Enables developers to easily incorporate high-quality 2D graphics, text, and images in applications and in applets. Drag and Drop Support (Java 2 Platform only) Provides the ability to drag and drop between a Java application and a native application.
TM TM TM

The first three JFC features were implemented without any native code, relying only on the API defined in JDK 1.1. As a result, they could and did become available as an extension to JDK 1.1. This extension was released as JFC 1.1, which is sometimes called "the Swing release." The API in JFC 1.1 is often called "the Swing API."

Note: "Swing" was the codename of the project that developed the new components. Although it's an unofficial name, it's frequently used to refer to the new components and related API. It's immortalized in the package names for the Swing API, which begin with javax.swing. This trail concentrates on the Swing components. We help you choose the appropriate ones for your GUI, tell you how to use them, and give you the background information you need to use them effectively. We discuss the Pluggable look and feel and Accessibility support when they affect how you write programs that use Swing components. This trail does not cover the JFC features that appear only in the Java 2 Platform. For information about those, refer to 2D Graphics and to the JFC Home Page . The following snapshots show three views of a GUI that uses Swing components. Each picture shows the same program, but with a different look and feel. The program, called Converter, is discussed in detail at the end of the next lesson, Swing Features and Concepts . Java look and feel CDE/Motif look and feel

Windows look and feel

Which Releases Contain the Swing API?


The Swing API is available in two forms:

As a core part of the Java 2 Platform (standard edition of either v 1.2 or v 1.3) JFC 1.1 (for use with JDK 1.1)

Which release you use depends on whether you need to use JDK 1.1 or the Java 2 Platform, and on whether you're willing to be a beta tester for SDK v 1.3. It's a bit simpler to use the Java 2 Platform because the JFC is built into the Java 2 Platform and you don't need to add libraries to be able to use the Swing API. However, if you need to use JDK 1.1, then adding the Swing API (using JFC 1.1) isn't difficult. Instructions for doing both are in Compiling and Running Swing Programs.

This trail describes the Swing 1.1 API, which is the version present in the Java 2 Platform v 1.2 and in the release called "JFC 1.1 (with Swing 1.1)." Except where noted, the code in this trail works unchanged with either release and subsequent compatible releases, such as SDK v 1.3 and JFC 1.1 (with Swing 1.1.1). Sun has released many versions of JFC 1.1, which are identified by the version of Swing API they contain. One previous version, for example, was called "JFC 1.1 (with Swing 1.0.3)." The last JFC 1.1 release was Swing version 1.1.1. It had the same API as Swing 1.1, but added many bug fixes, some performance improvements, and a few new capabilities such as HTML text in labels that required no API changes. The following table shows some of the important releases containing Swing API. Bold font indicates the releases typically used in shipping products. Corresponding Corresponding Java 2 Platform Comments JFC 1.1 Release Version (Standard Edition) JFC 1.1 The release of JFC 1.1 included in Swing 1.0.3 none (with Swing 1.0.3) Java Plug-in 1.1.1. The first releases containing the Swing 1.1 final Swing 1.1 API supported for use in shipping products. Java JFC 1.1 v 1.2, v 1.2.1 Plug-in 1.1.2 and Java Plug-in 1.2 Note: This is (with Swing 1.1) provide applet support for JDK 1.1 the API this + Swing 1.1 and Java 2 Platform trail covers. v 1.2, respectively. Adds performance enhancements, Swing 1.1.1 JFC 1.1 many bug fixes, and selected new (with Swing 1.1.1) functionality (requiring no API changes) to Swing 1.1. Java PlugNote: This v 1.2.2 in 1.1.3 and Java Plug-in 1.2.2 trail includes Note: This is the provide applet support for JDK 1.1 notes about last release that + Swing 1.1.1 and Java 2 Platform this API. supports JDK 1.1. v 1.2.2, respectively. Adds significant performance enhancements and bug fixes, along with some new features and API no separate additions. For more information, "Swing" none v 1.3 Beta see the release documentation , version especially Swing Changes and New number Features . Java Plug-in 1.3 Beta provides applet support for this release. Swing API Version
TM

What Swing Packages Should I Use?


The Swing API is powerful, flexible -- and immense. For example, the 1.1 version of the API has 15 public packages: javax.accessibility, javax.swing, javax.swing.border, javax.swing.colorchooser, javax.swing.event, javax.swing.filechooser, javax.swing.plaf, javax.swing.plaf.basic, javax.swing.plaf.metal, javax.swing.plaf.multi, javax.swing.table, javax.swing.text, javax.swing.text.html, javax.swing.tree, and javax.swing.undo. Fortunately, most programs use only a small subset of the API. This trail sorts out the API for you, giving you examples of common code and pointing you to methods and classes you're likely to need. Most of the code in this trail uses only one or two Swing packages:
javax.swing javax.swing.event

(not always required)

How Are Swing Components Different from AWT Components?


If you don't care about the AWT components, skip to the next section. You can get a more general introduction to the Swing components from A Quick Tour of a Swing Application's Code and from the Swing Features and Concepts lesson. The AWT components are those provided by the JDK 1.0 and 1.1 platforms. Although the Java 2 Platform still supports the AWT components, we strongly encourage you to use Swing components instead. You can identify Swing components because their names start with J. The AWT button class, for example, is named Button, while the Swing button class is named JButton. Additionally, the AWT components are in the java.awt package, while the Swing components are in the javax.swing package. The biggest difference between the AWT components and Swing components is that the Swing components are implemented with absolutely no native code. Since Swing components aren't restricted to the least common denominator -- the features that are present on every platform -- they can have more functionality than AWT components. Because the Swing components have no native code, they can be be shipped as an add-on to JDK 1.1, in addition to being part of the Java 2 Platform. Even the simplest Swing components have capabilities far beyond what the AWT components offer:

Swing buttons and labels can display images instead of, or in addition to, text. You can easily add or change the borders drawn around most Swing components. For example, it's easy to put a box around the outside of a container or label. You can easily change the behavior or appearance of a Swing component by either invoking methods on it or creating a subclass of it.

Swing components don't have to be rectangular. Buttons, for example, can be round. Assistive technologies such as screen readers can easily get information from Swing components. For example, a tool can easily get the text that's displayed on a button or label.

Swing lets you specify which look and feel your program's GUI uses. By contrast, AWT components always have the look and feel of the native platform. Another interesting feature is that Swing components with state use models to keep the state. A JSlider, for instance, uses a BoundedRangeModel object to hold its current value and range of legal values. Models are set up automatically, so you don't have to deal with them unless you want to take advantage of the power they can give you. If you're used to using AWT components, you need to be aware of a few gotchas when using Swing components:

Programs should not, as a rule, use "heavyweight" components alongside Swing components. Heavyweight components include all the ready-to-use AWT components (such as Menu and ScrollPane) and all components that inherit from the AWT Canvas and Panel classes. This restriction exists because when Swing components (and all other "lightweight" components) overlap with heavyweight components, the heavyweight component is always painted on top. For more information, see Mixing Heavy and Light Components, an article in The Swing Connection. Swing components aren't thread safe. If you modify a visible Swing component -invoking its setText method, for example -- from anywhere but an event handler, then you need to take special steps to make the modification execute on the eventdispatching thread. This isn't an issue for many Swing programs, since component-modifying code is typically in event handlers. The containment hierarchy for any window or applet that contains Swing components must have a Swing top-level container at the root of the hierarchy. For example, a main window should be implemented as a JFrame instance rather than as a Frame instance. You don't add components directly to a top-level container such as a JFrame. Instead, you add components to a container (called the content pane) that is itself contained by the JFrame.

Converting to Swing tells you more about the differences between Swing components and AWT components

A Visual Index to the Swing Components


Top-Level Containers

Applet

Dialog

Frame

General-Purpose Containers

Panel

Scroll pane

Split pane

Tabbed pane

Tool bar

Special-Purpose Containers

Internal frame

Layered pane

Root pane

Basic Controls

Buttons

Combo box

List

Menu

Slider

Text fields

Uneditable Information Displays

Label

Progress bar

Tool tip

Editable Displays of Formatted Information

Color chooser

File chooser

Table

Text

Tree

How to Use Labels


With the JLabel class, you can display unselectable text and images. If you need to create a component that displays a string or an image (or both), optionally reacting to user input, you can do so by using or extending JLabel. If the interactive component has state, then you should probably use a button instead of a label. Here's a picture of an application that displays three labels. The window is divided into three rows of equal height; the label in each row is as wide as possible.

Try this: 1. Compile and run the application. The source code is in LabelDemo.java , and the image is middle.gif. See Getting Started with Swing if you need help compiling or running this application. 2. Resize the window so you can see how the labels' contents are placed with the labels' drawing area. All the label contents have the default vertical alignment -- the label contents are

centered vertically in the label's drawing area. The top label, which contains both image and text, is specified to have horizontal center alignment. The second label, which contains just text, has the left alignment that is the default for text-only labels. The third label, which contains just an image, has horizontal center alignment, which is the default for image-only labels.

Below is the code from LabelDemo.java that creates the labels in the previous example.
ImageIcon icon = new ImageIcon("images/middle.gif"); . . . label1 = new JLabel("Image and Text", icon, JLabel.CENTER); //Set the position of the text, relative to the icon: label1.setVerticalTextPosition(JLabel.BOTTOM); label1.setHorizontalTextPosition(JLabel.CENTER); label2 = new JLabel("Text-Only Label"); label3 = new JLabel(icon); //Add labels to the JPanel. add(label1); add(label2); add(label3);

Note that label alignment is different from X and Y alignment. X and Y alignment are used by layout managers and can affect the way any component -- not just a label -- is sized or positioned. Label alignment, on the other hand, has no effect on a label's size or position. It simply determines where, inside the label's painting area, the label's contents are positioned. In the usual case, the label's painting area is exactly the size needed to paint the label, and thus label alignment is irrelevant. For more information about X and Y alignment, see How to Use BoxLayout . Often, a label describes another component. When this is true, you can improve your program's accessibility by using the setLabelFor method to identify the component the label describes. For example:
amountLabel.setLabelFor(amountField); The preceding code, taken from the TextFieldDemo

example discussed in How to Use Text Fields, lets assistive technologies know that the label (amountLabel) provides information about the text field (amountField). For more information about assistive technologies, see How to Support Assistive Technologies .

Using HTML on a Label


Note: The information in this section documents a feature available only in Swing 1.1.1 Beta 1 or compatible releases.

Have you ever wanted to put multiple lines on a label? Have you ever wanted to make part of a label bold or italic? Now you can. As of Swing 1.1.1 Beta 1, JLabel supports multiple lines, multiple fonts, and a whole lot more because you can specify a label's text using HTML. Here's an application that dynamically sets the text on a label.

Try this: 1. Compile and run the application. The source code is in HtmlDemo.java . See Getting Started with Swing if you need help compiling or running this application. Make sure you compile this program and run it using Swing 1.1.1 Beta 1 or a compatible release. 2. Edit the HTML in the text area at the left and click the Change the label button. The label at the right shows the result. 3. Remove <html> from the text area on the left. The label at the right shows the result. The action listener for the button executes this single line of code:
theLabel.setText(htmlTextArea.getText());

If the string in the text area on the left begins with <html>, then the label parses it as HTML. Otherwise, the label assumes it's straight text. Because this is an early release of this feature, there are some gotchas to be aware of:

Don't use <br> in your HTML. The label's preferred size won't be computed correctly (it will be computed as if the <br> weren't there). Use a regular paragraph tag (<p>) instead . If you specify an invalid HTML tag, an exception is thrown deep in the text package. Fix your HTML and try again.

As of Swing 1.1.1 Beta 1, you can use HTML to set the text for labels and buttons. In the near future, many more Swing components -- tool tips, tabbed panes, and menu items, for example -- will support HTML. Warning: There is no programmatic way to test whether a component supports HTML text. Do not specify HTML text unless you are absolutely sure that your program is running in a release that supports HTML text in the desired component.

The Label API


The following tables list the commonly used JLabel constructors and methods. Other methods you're likely to call are defined by the Component and JComponent classes. They include setFont, setForeground, setBorder, setOpaque, and setBackground. See The JComponent Class for details. The API for using labels falls into three categories:

Setting or Getting the Label's Contents Fine Tuning the Label's Appearance Supporting Accessibility

Setting or Getting the Label's Contents Method or Constructor Purpose Create a JLabel instance, initializing it to have the specified text/image/alignment. The int argument JLabel(Icon) specifies the horizontal alignment of the label's contents JLabel(Icon, int) JLabel(String) within its drawing area. The horizontal alignment must JLabel(String, Icon, int) be one of the following constants defined in the JLabel(String, int) SwingConstants interface (which JLabel JLabel() implements): LEFT, CENTER, RIGHT, LEADING, or TRAILING.
void setText(String) String getText() void setIcon(Icon) Icon getIcon()

Set or get the text displayed by the label. Set or get the image displayed by the label. Set or get the letter that should look like a keyboard

void alternative. This is handy when a label describes a setDisplayedMnemonic(char) char getDisplayedMnemonic() component (such as a text field) that has a keyboard

alternative but can't display it. Set or get the image displayed by the label when it's void setDisabledIcon(Icon) disabled. If you don't specify a disabled image, then the Icon getDisabledIcon() look-and-feel creates one by manipulating the default image. Fine Tuning the Label's Appearance Method Purpose void Set or get where in the label its contents should be

placed. The SwingConstants interface defines five possible values for horizontal alignment: LEFT setHorizontalAlignment(int) void setVerticalAlignment(int) (the default for text-only labels), CENTER (the int getHorizontalAlignment() default for image-only labels), RIGHT, LEADING, int getVerticalAlignment() and TRAILING. For vertical alignment: TOP, CENTER (the default), and BOTTOM.
void Set or get where the button's text should be placed, setHorizontalTextPosition(int) relative to the button's image. The void SwingConstants interface defines three possible setVerticalTextPosition(int) int getHorizontalTextPosition() values for horizontal position: LEFT, CENTER, and RIGHT (the default). For vertical position: TOP, int getVerticalTextPosition() CENTER (the default), and BOTTOM. void setIconTextGap(int) int getIconTextGap()

Method
Component getLabelFor()

Set or get the number of pixels between the label's text and its image. Supporting Accessibility Purpose Set or get which component the label describes.

void setLabelFor(component)

Examples that Use Labels


The following table lists some of the many examples that use labels. Where Example Notes Described Shows how to specify horizontal and vertical LabelDemo This section alignment, as well as aligning a label's text and image. Lets you experiment with specifying HTML text HtmlDemo This section for a label. Fixing Demonstrates a possible alignment problem AlignmentDemo Alignment when using a label in a vertical box layout. Problems Shows how to solve the problem. How to Use Uses a changeable label to display instructions DialogDemo Dialogs and provide feedback. How to Use Split Panes and Displays an image using a label inside of a scroll SplitPaneDemo How to Use pane. Lists. How to Use SliderDemo2 Uses JLabel to provide labels for a slider. Sliders Implements a label subclass, ColorRenderer, to How to Use TableDialogEditDemo Tables display colors in table cells.

TextFieldDemo

How to Use Text Fields

TextComponentDemo

ColorChooserDemo

Has four rows, each containing a label and the text field it describes. Has an inner class (CaretListenerLabel) that General Rules extends JLabel to provide a label that listens for for Using Text events, updating itself based on the events. To Components run the example, you also need LimitedStyledDocument.java . How to Use Uses an opaque label to display the currently Color Choosers chosen color against a fixed-color background.

How to Use Buttons, Check Boxes, and Radio Buttons


To create a button, you can instantiate one of the many classes that descend from the AbstractButton class. The following table shows the Swing-defined AbstractButton subclasses that you might want to use: Class
JButton

Summary A common button.

JCheckBox

A check box button. One of a group of radio buttons. JMenuItem An item in a menu. How to Use Menus JCheckBoxMenuItem A menu item that has a How to Use Menus and How to checkbox. Use Check Boxes JRadioButtonMenuItem A menu item that has a radio How to Use Menus and How to button. Use Radio Buttons JToggleButton Implements toggle Used to implement the crayon functionality inherited by buttons in How to Use Color JCheckBox and Choosers, the cm button in How to Use Scroll Panes, and JRadioButton. Can be instantiated or subclassed to NumberButton in the BINGO! create two-state buttons. Note: If you want to collect a group of buttons into a row or column, then you should check out tool bars. First, this section explains the basic button API that AbstractButton defines -- and thus all Swing buttons have in common. Next, it describes the small amount of API that JButton adds to AbstractButton. After that, this section shows you how to use specialized API to implement check boxes and radio buttons.
JRadioButton

Where Described How to Use the Common Button API and How to Use JButton Features How to Use Check Boxes How to Use Radio Buttons

How to Use the Common Button API


Here is a picture of an application that displays three buttons:

Try this: 1. Compile and run the application. The source file is ButtonDemo.java . You will also need to put three image files in a directory named images: left.gif, middle.gif, and right.gif. See Getting Started with Swing if you need help compiling or running this application. 2. Click the left button. It disables the middle button (and itself, since it's no longer useful) and enables the right button. 3. Click the right button. It enables the middle button and the left button, and disables itself.

As the ButtonDemo example shows, a Swing button can display both text and an image. In ButtonDemo, each button has its text in a different place, relative to its image. The underlined letter in each button's text shows the mnemonic -- the keyboard alternative -for each button. When a button is disabled, the look and feel automatically generates the button's disabled appearance. However, you could provide an image to be substituted for the normal image. For example, you could provide gray versions of the images used in the left and right buttons. How you implement event handling depends on the type of button you use and how you use it. Generally, you implement an action listener , which is notified every time the user clicks the button. For check boxes you usually use an item listener , which is notified when the check box is selected or deselected. Below is the code from ButtonDemo.java that creates the buttons in the previous example and reacts to button clicks. The bold code is the code that would remain if the buttons had no images.
//In initialization code: ImageIcon leftButtonIcon = new ImageIcon("images/right.gif"); ImageIcon middleButtonIcon = new ImageIcon("images/middle.gif"); ImageIcon rightButtonIcon = new ImageIcon("images/left.gif"); b1 = new JButton("Disable middle button", leftButtonIcon);

b1.setVerticalTextPosition(AbstractButton.CENTER); b1.setHorizontalTextPosition(AbstractButton.LEFT); b1.setMnemonic(KeyEvent.VK_D); b1.setActionCommand("disable"); b2 = new JButton("Middle button", middleButtonIcon); b2.setVerticalTextPosition(AbstractButton.BOTTOM); b2.setHorizontalTextPosition(AbstractButton.CENTER); b2.setMnemonic(KeyEvent.VK_M); b3 = new JButton("Enable middle button", rightButtonIcon); //Use the default text position of CENTER, RIGHT. b3.setMnemonic(KeyEvent.VK_E); b3.setActionCommand("enable"); b3.setEnabled(false); //Listen for actions on buttons 1 and 3. b1.addActionListener(this); b3.addActionListener(this); b1.setToolTipText("Click this button to disable " + "the middle button."); b2.setToolTipText("This middle button does nothing " + "when you click it."); b3.setToolTipText("Click this button to enable the " + "middle button."); ...

public void actionPerformed(java.awt.event.ActionEvent e) { if (e.getActionCommand().equals("disable")) { b2.setEnabled(false); b1.setEnabled(false); b3.setEnabled(true); } else { b2.setEnabled(true); b1.setEnabled(true); b3.setEnabled(false); } }

How to Use JButton Features


Ordinary buttons -- JButton objects -- have just a bit more functionality than the AbstractButton class provides. You can make a JButton be the default button, and if you're using the right release, you can specify the text and formatting of a button's label using HTML. At most one button in a top-level container can be the default button. The default button typically has a highlighted appearance and acts clicked whenever the top-level container has the keyboard focus and the user presses the Return or Enter key. The exact implementation depends on the look and feel. Here is a picture of a dialog, implemented in ListDialog.java in which the Set button is the default button:

You set the default button by invoking the setDefaultButton method on a top-level container's root pane. Here is the code that sets up the default button for the ListDialog example:
//In the constructor for a JDialog subclass: getRootPane().setDefaultButton(setButton);

In the Swing 1.1.1 Beta 1 release of JFC 1.1, the Swing team added the ability to use HTML to specify a button's text. To do so, simply put the <html> tag at the beginning of a string, then use any valid HTML in the remainder of the string. Using HTML can be useful for varying the text font or color within a button, and for putting line breaks in a button. Here's an example of specifying HTML for the buttons in ButtonDemo:
b1 = new JButton("<html><font size=-1><b><u>D</u>isable</b>" + " middle button</font>", leftButtonIcon); ... b2 = new JButton("<html><font size=-1>Middle button</font>", middleButtonIcon); ... b3 = new JButton("<html><font size=-1><b><u>E</u>nable</b>" + " middle button</font>", rightButtonIcon);

Here is a picture of the buttons when the program is run in a platform that supports Swing 1.1.1 Beta 1 or a compatible release:

This figure has been reduced to fit on the page. Click the image to view it at its natural size. Note that we had to use a <u> tag to cause the mnemonic character to be underlined in the button. The middle button has no underlined character because we didn't use the <u> tag in it. Note also that when a button is disabled, its HTML text remains dark, instead of becoming gray.

Warning: Don't use HTML in buttons unless you're absolutely sure that the program is running in a release that supports this feature. In releases that support only the Swing 1.1 API, putting HTML in a button results in one ugly-looking button, such as this one:

For more information, see Using HTML on a Label.

How to Use Check Boxes


The JCheckBox class provides support for check box buttons. You can also put check boxes in menus, using the JCheckBoxMenuItem class. Because JCheckBox and JCheckBoxMenuItem inherit from AbstractButton, Swing check boxes have all the usual button characteristics, as discussed earlier in this section. For example, you can specify images to be used in check boxes. Check boxes are similar to radio buttons but their selection model is different, by convention. Any number of check boxes in a group -- none, some, or all -- can be selected. A group of radio buttons, on the other hand, can have only one button selected. Here is a picture of an application that uses four check boxes to customize a cartoon:

Try this: 1. Compile and run the application. The source file is CheckBoxDemo.java . You will also need to put 16 image files in a directory named images/geek. See the examples index for links to all the files required by this example. See Getting Started with Swing if you need help compiling or running this application. 2. Click the Chin button or press Alt-c. The Chin check box becomes unselected, and the chin disappears from the picture. The other check boxes remain selected. This application has one item listener that listens to all the check boxes. Each time the item listener receives an event, the application loads a new picture that reflects the current state of the check boxes.

A check box generates one item event and one action event per click. Usually, you listen only for item events, since they let you determine whether the click selected or deselected the check box. Below is the code from CheckBoxDemo.java that creates the check boxes in the previous example and reacts to clicks.
//In initialization code: chinButton = new JCheckBox("Chin"); chinButton.setMnemonic(KeyEvent.VK_C); chinButton.setSelected(true); glassesButton = new JCheckBox("Glasses"); glassesButton.setMnemonic(KeyEvent.VK_G); glassesButton.setSelected(true); hairButton = new JCheckBox("Hair"); hairButton.setMnemonic(KeyEvent.VK_H); hairButton.setSelected(true); teethButton = new JCheckBox("Teeth"); teethButton.setMnemonic(KeyEvent.VK_T); teethButton.setSelected(true); // Register a listener for the check boxes. CheckBoxListener myListener = new CheckBoxListener(); chinButton.addItemListener(myListener); glassesButton.addItemListener(myListener); hairButton.addItemListener(myListener); teethButton.addItemListener(myListener);

... class CheckBoxListener implements ItemListener { public void itemStateChanged(ItemEvent e) { ... Object source = e.getItemSelectable(); if (source == chinButton) { //...make a note of it... } else if (source == glassesButton) { //...make a note of it... } else if (source == hairButton) { //...make a note of it... } else if (source == teethButton) { //...make a note of it... }

} }

if (e.getStateChange() == ItemEvent.DESELECTED) //...make a note of it... picture.setIcon(/* new icon */); ...

Note: In a future release, we expect check boxes to support HTML text. See Using HTML on a Label for information about HTML text support.

How to Use Radio Buttons

Radio buttons are groups of buttons in which, by convention, only one button at a time can be selected. The Swing release supports radio buttons with the JRadioButton and ButtonGroup classes. To put a radio button in a menu, use the JRadioButtonMenuItem class. Other ways of displaying one-of-many choices are combo boxes and lists. Radio buttons look similar to check boxes, but, by convention, check boxes place no limits on how many items can be selected at a time. Because JRadioButton inherits from AbstractButton, Swing radio buttons have all the usual button characteristics, as discussed earlier in this section. For example, you can specify the image displayed in a radio button. Here is a picture of an application that uses five radio buttons to let you choose which kind of pet is displayed:

Try this: 1. Compile and run the application. The source file is RadioButtonDemo.java . You will also need to put five image files in a directory named images. See the examples index for links to all the files required by this example. See Getting Started with Swing if you need help compiling or running this application. 2. Click the Dog button or press Alt-d. The Dog button becomes selected, which makes the Bird button become unselected. The picture switches from a bird to a dog. This application has one action listener that listens to all the radio buttons. Each time the action listener receives an event, the application displays the picture for the radio button that was just clicked.

Each time the user clicks a radio button (even if it was already selected), the button fires an action event . One or two item events also occur -- one from the button that was just selected, and another from the button that lost the selection (if any). Usually, you handle radio button clicks using an action listener. Below is the code from RadioButtonDemo.java that creates the radio buttons in the previous example and reacts to clicks.

//In initialization code: // Create the radio buttons. JRadioButton birdButton = new JRadioButton(birdString); birdButton.setMnemonic(KeyEvent.VK_B); birdButton.setActionCommand(birdString); birdButton.setSelected(true); JRadioButton catButton = new JRadioButton(catString); catButton.setMnemonic(KeyEvent.VK_C); catButton.setActionCommand(catString); JRadioButton dogButton = new JRadioButton(dogString); dogButton.setMnemonic(KeyEvent.VK_D); dogButton.setActionCommand(dogString); JRadioButton rabbitButton = new JRadioButton(rabbitString); rabbitButton.setMnemonic(KeyEvent.VK_R); rabbitButton.setActionCommand(rabbitString); JRadioButton pigButton = new JRadioButton(pigString); pigButton.setMnemonic(KeyEvent.VK_P); pigButton.setActionCommand(pigString); // Group the radio buttons. ButtonGroup group = new ButtonGroup(); group.add(birdButton); group.add(catButton); group.add(dogButton); group.add(rabbitButton); group.add(pigButton); // Register a listener for the radio buttons. RadioListener myListener = new RadioListener(); birdButton.addActionListener(myListener); catButton.addActionListener(myListener); dogButton.addActionListener(myListener); rabbitButton.addActionListener(myListener); pigButton.addActionListener(myListener); ... class RadioListener implements ActionListener ... { public void actionPerformed(ActionEvent e) { picture.setIcon(new ImageIcon("images/" + e.getActionCommand() + ".gif")); } }

For each group of radio buttons, you need to create a ButtonGroup instance and add each radio button to it. The ButtonGroup takes care of unselecting the previously selected button when the user selects another button in the group. You should generally initialize a group of radio buttons so that one is selected. However, the API doesn't enforce this rule -- a group of radio buttons can have no initial selection. Once the user has made a selection, exactly one button is selected from then on. There's no supported API for unselecting all the buttons. However, if you really want to unselect

all the buttons (not that we recommend it), invoking setSelected(null, true) on the ButtonGroup should do the trick. Note: In a future release, we expect radio buttons to support HTML text. See Using HTML on a Label for information about HTML text support.

The Button API


The following tables list the commonly used button-related API. You can see most of this API in action by playing with the Buttons, Radio Buttons, and Check Boxes panes in the SwingSet example that's part of the Swing release. See the release's top-level README file for help finding and using SwingSet. Other methods you might call are listed in the API tables in The JComponent Class. The API for using buttons falls into these categories:

Setting or Getting the Button's Contents Fine Tuning the Button's Appearance Implementing the Button's Functionality Check Box Constructors Radio Button Constructors Toggle Button Constructors Commonly Used ButtonGroup Constructors/Methods Setting or Getting the Button's Contents Method or Constructor Purpose

JButton(String, Icon) JButton(String) JButton(Icon) JButton() void setText(String) String getText() void setIcon(Icon) Icon getIcon() void setDisabledIcon(Icon) Icon getDisabledIcon() void setPressedIcon(Icon) Icon getPressedIcon() void setSelectedIcon(Icon) Icon getSelectedIcon() void setDisabledSelectedIcon(Icon) Icon getDisabledSelectedIcon()

Create a JButton instance, initializing it to have the specified text/image. Set or get the text displayed by the button. Set or get the image displayed by the button when the button isn't selected or pressed. Set or get the image displayed by the button when it's disabled. If you don't specify a disabled image, then the look and feel creates one by manipulating the default image. Set or get the image displayed by the button when it's being pressed. Set or get the image displayed by the button when it's selected. If you don't specify a disabled selected image, then the look and feel creates one by manipulating the selected image.

setRolloverEnabled(boolean) boolean getRolloverEnabled() Use setRolloverEnabled(true) and void setRolloverIcon(Icon) setRolloverIcon(someIcon) to make the button Icon getRolloverIcon() display the specified icon when the cursor passes void setRolloverSelectedIcon(Icon) over it. Icon getRolloverSelectedIcon()

Fine Tuning the Button's Appearance Method or Constructor Purpose Set or get where in the button its contents should be void placed. The AbstractButton class allows any one setHorizontalAlignment(int) void setVerticalAlignment(int) of the following values for horizontal alignment: int getHorizontalAlignment() LEFT, CENTER (the default), and RIGHT. For vertical int getVerticalAlignment() alignment: TOP, CENTER (the default), and BOTTOM.
void Set or get where the button's text should be placed, setHorizontalTextPosition(int) relative to the button's image. The void AbstractButton class allows any one of the setVerticalTextPosition(int) int getHorizontalTextPosition() following values for horizontal position: LEFT, CENTER, and RIGHT (the default). For vertical int getVerticalTextPosition() position: TOP, CENTER (the default), and BOTTOM.

Set or get the number of pixels between the button's border and its contents. void setFocusPainted(boolean) Set or get whether the button should look different boolean isFocusPainted() when it has the focus. void setBorderPainted(boolean) Set or get whether the border of the button should boolean isBorderPainted() be painted. Implementing the Button's Functionality Method or Constructor Purpose Set or get the keyboard alternative to clicking the button. One form of the setMnemonic method accepts a character argument; however, void setMnemonic(int) char getMnemonic() the Swing team recommends that you use an int argument instead, specifying a KeyEvent.VK_X constant.
void setMargin(Insets) Insets getMargin() void setActionCommand(String) String getActionCommand(void) void addActionListener(ActionListener) ActionListener removeActionListener() void addItemListener(ItemListener)

Set or get the name of the action performed by the button. Add or remove an object that listens for action events fired by the button.

Add or remove an object that listens for item ItemListener removeItemListener() events fired by the button.
void setSelected(boolean)

Set or get whether the button is selected. Makes

sense only for buttons that have on/off state, such as check boxes. Programmatically perform a "click". The void doClick() optional argument specifies the amount of time void doClick(int) (in milliseconds) that the button should look pressed. Check Box Constructors Constructor Purpose Create a JCheckBox instance. The string argument JCheckBox(String) JCheckBox(String, boolean) specifies the text, if any, that the check box should display. Similarly, the Icon argument specifies the JCheckBox(Icon) JCheckBox(Icon, boolean) image that should be used instead of the look and feel's JCheckBox(String, Icon) default check box image. Specifying the boolean JCheckBox(String, Icon, argument as true initializes the check box to be boolean) selected. If the boolean argument is absent or false, JCheckBox() then the check box is initially unselected.
boolean isSelected() JCheckBoxMenuItem(String) JCheckBoxMenuItem(String, boolean) JCheckBoxMenuItem(Icon) JCheckBoxMenuItem(String, Icon) JCheckBoxMenuItem(String, Icon, boolean) JCheckBoxMenuItem()

Create a JCheckBoxMenuItem instance. The arguments are interpreted in the same way as the arguments to the JCheckBox constructors, except that any specified icon is shown in addition to the normal check box icon. Radio Button Constructors

Purpose Creates a JRadioButton instance. The string argument specifies the text, if any, that the radio JRadioButton(String) JRadioButton(String, boolean) button should display. Similarly, the Icon argument specifies the image that should be used instead of the JRadioButton(Icon) look and feel's default radio button image. Specifying JRadioButton(Icon, boolean) the boolean argument as true initializes the radio JRadioButton(String, Icon) button to be selected, subject to the approval of the JRadioButton(String, Icon, boolean) ButtonGroup object. If the boolean argument is JRadioButton() absent or false, then the radio button is initially unselected. JRadioButtonMenuItem(String) Creates a JRadioButtonMenuItem instance. The arguments are interpreted in the same way as the JRadioButtonMenuItem(Icon) JRadioButtonMenuItem(String, arguments to the JRadioButton constructors, except Icon) that any specified icon is shown in addition to the JRadioButtonMenuItem() normal radio button icon. Toggle Button Constructors Constructor Purpose

Constructor

JToggleButton(String) JToggleButton(String, boolean) JToggleButton(Icon) JToggleButton(Icon, boolean) JToggleButton(String, Icon) JToggleButton(String, Icon, boolean) JToggleButton()

Creates a JToggleButton instance, which is similar to a JButton, but with two states. Normally, you use a JRadioButton or JCheckBox instead of directly instantiating JToggleButton, but JToggleButton can be useful when you don't want the typical radio button or check box appearance. The string argument specifies the text, if any, that the toggle button should display. Similarly, the Icon argument specifies the image that should be used. Specifying the boolean argument as true initializes the toggle button to be selected. If the boolean argument is absent or false, then the toggle button is initially unselected. Commonly Used ButtonGroup Constructors/Methods Purpose Creates a ButtonGroup instance. Adds a button to the group, or removes a button from the group.

Constructor or Method
ButtonGroup() void add(AbstractButton) void remove(AbstractButton)

Examples that Use Various Kinds of Buttons


The following examples use buttons. Also see Examples that Use Tool Bars, which lists programs that add JButton objects to JToolBars. Where Example Notes Described How to Use the Uses mnemonics and icons. Specifies the button ButtonDemo Common Button text position, relative to the button icon. Uses action API commands. How to Use Implements a dialog with two buttons, one of which ListDialog JButton Features is the default button. The same example as is explained in How to Use Running Swing AppletDemo the Common Button API, but implemented as a Applets combined applet and application. Has "Show it" buttons whose behavior is tied to the How to Make state of radio buttons. Uses sizable, though DialogDemo Dialogs anonymous, inner classes to implement the action listeners. How to Monitor Implements a button's action listener with a named ProgressBarDemo Progress inner class. How to Use Uses check box buttons to determine which of 16 CheckBoxDemo Check Boxes images it should display. How to Use Uses check box menu items to set the state of the ActionDemo Actions program. How to Use Uses radio buttons to determine which of five RadioButtonDemo Radio Buttons images it should display.

DialogDemo MenuDemo

How to Make Dialogs How to Use Menus

Contains several sets of radio buttons, which it uses to determine which dialog to bring up. Contains radio button menu items and check box menu items.

Trail: Creating a GUI with JFC/Swing Lesson: Using Swing Components

How to Use Menus


A menu provides a space-saving way to let the user choose one of several options. Other components with which the user can make a one-of-many choice include combo boxes, lists, radio buttons, and tool bars. If any of your menu items performs an action that is duplicated by another menu item or by a tool-bar button, then in addition to this section you should read How to Use Actions. Menus are unique in that, by convention, they aren't placed with the other components in the UI. Instead, a menu usually appears either in a menu bar or as a popup menu. A menu bar contains one or more menus and has a customary, platform-dependent location -usually along the top of a window. A popup menu is a menu that is invisible until the user makes a platform-specific mouse action, such as pressing the right mouse button, over a popup-enabled component. The popup menu then appears under the cursor. The following figure shows the Swing components that implement each part of the menu system.

The rest of this section teaches you about the menu components and tells you how to use various menu features:

The menu component hierarchy Creating menus Handling events from menu items Enabling keyboard operation Bringing up a popup menu Customizing menu layout The Menu API Examples that use menus

The Menu Component Hierarchy


Here is a picture of the inheritance hierarchy for the menu-related classes:

As the figure shows, menu items (including menus) are simply buttons. You might be wondering how a menu, if it's only a button, shows its menu items. The answer is that when a menu is activated, it automatically brings up a popup menu that displays the menu items.

Creating Menus
The following code creates the menus shown near the beginning of this menu section. The bold lines of code create and connect the menu objects; the other code sets up or customizes the menu objects. You can find the entire program in MenuLookDemo.java . To run the program, you need to have the following image file: images/middle.gif. Note: Because this code has no event handling, the menus do nothing useful except look like they should. If you run the example, you'll notice that despite the lack of custom event handling, menus and submenus appear when they should, and the check boxes and radio buttons respond appropriately when the user chooses them.
//in the constructor for a JFrame subclass: JMenuBar menuBar; JMenu menu, submenu; JMenuItem menuItem;

JCheckBoxMenuItem cbMenuItem; JRadioButtonMenuItem rbMenuItem; ... //Create the menu bar. menuBar = new JMenuBar(); setJMenuBar(menuBar); //Build the first menu. menu = new JMenu("A Menu"); menu.setMnemonic(KeyEvent.VK_A); menu.getAccessibleContext().setAccessibleDescription( "The only menu in this program that has menu items"); menuBar.add(menu); //a group of JMenuItems menuItem = new JMenuItem("A text-only menu item", KeyEvent.VK_T); menuItem.setAccelerator(KeyStroke.getKeyStroke( KeyEvent.VK_1, ActionEvent.ALT_MASK)); menuItem.getAccessibleContext().setAccessibleDescription( "This doesn't really do anything"); menu.add(menuItem); menuItem = new JMenuItem("Both text and icon", new ImageIcon("images/middle.gif")); menuItem.setMnemonic(KeyEvent.VK_B); menu.add(menuItem); menuItem = new JMenuItem(new ImageIcon("images/middle.gif")); menuItem.setMnemonic(KeyEvent.VK_D); menu.add(menuItem); //a group of radio button menu items menu.addSeparator(); ButtonGroup group = new ButtonGroup(); rbMenuItem = new JRadioButtonMenuItem("A radio button menu item"); rbMenuItem.setSelected(true); rbMenuItem.setMnemonic(KeyEvent.VK_R); group.add(rbMenuItem); menu.add(rbMenuItem); rbMenuItem = new JRadioButtonMenuItem("Another one"); rbMenuItem.setMnemonic(KeyEvent.VK_O); group.add(rbMenuItem); menu.add(rbMenuItem); //a group of check box menu items menu.addSeparator(); cbMenuItem = new JCheckBoxMenuItem("A check box menu item"); cbMenuItem.setMnemonic(KeyEvent.VK_C); menu.add(cbMenuItem); cbMenuItem = new JCheckBoxMenuItem("Another one"); cbMenuItem.setMnemonic(KeyEvent.VK_H); menu.add(cbMenuItem); //a submenu

menu.addSeparator(); submenu = new JMenu("A submenu"); submenu.setMnemonic(KeyEvent.VK_S); menuItem = new JMenuItem("An item in the submenu"); menuItem.setAccelerator(KeyStroke.getKeyStroke( KeyEvent.VK_2, ActionEvent.ALT_MASK)); submenu.add(menuItem); menuItem = new JMenuItem("Another item"); submenu.add(menuItem); menu.add(submenu); //Build second menu in the menu bar. menu = new JMenu("Another Menu"); menu.setMnemonic(KeyEvent.VK_N); menu.getAccessibleContext().setAccessibleDescription( "This menu does nothing"); menuBar.add(menu);

As the code shows, to set the menu bar for a JFrame, you use the setJMenuBar method. To add a JMenu to a JMenuBar, you use the add(JMenu) method. To add menu items and submenus to a JMenu, you use the add(JMenuItem) method. Other methods in the preceding code include setAccelerator and setMnemonic, which are discussed in Enabling Keyboard Operation. The setAccessibleDescription method is discussed in How to Support Assistive Technologies .

Handling Events from Menu Items


To detect when the user selects a JMenuItem, you can listen for action events (just as you would for a JButton). To detect when the user selects a JRadioButtonMenuItem, you can listen for either action events or item events, as described in How to Use Radio Buttons. For JCheckBoxMenuItems, you generally listen for item events, as described in How to Use Check Boxes. The following picture shows a program that adds event detection to the preceding example. The program's code is in MenuDemo.java . Like MenuLookDemo, MenuDemo uses the images/middle.gif image file.

Here is the code that implements the event handling:


public class MenuDemo ... implements ActionListener, ItemListener { ... public MenuDemo() { //...for each JMenuItem instance: menuItem.addActionListener(this); ... //for each JRadioButtonMenuItem: rbMenuItem.addActionListener(this); ... //for each JCheckBoxMenuItem: cbMenuItem.addItemListener(this); ... } public void actionPerformed(ActionEvent e) { //...Get information from the action event... //...Display it in the text area... } public void itemStateChanged(ItemEvent e) { //...Get information from the item event... //...Display it in the text area... }

For examples of handling action and item events, see the button, radio button, and check box sections, as well as the list of examples at the end of this section.

Enabling Keyboard Operation


Menus support two kinds of keyboard alternatives: mnemonics and accelerators. Mnemonics offer a way to use the keyboard to navigate the menu hierarchy, increasing the accessibility of programs. Accelerators, on the other hand, offer keyboard shortcuts to bypass navigating the menu hierarchy. Mnemonics are for all users; accelerators are for power users.

A mnemonic is a key that makes an already visible menu item be chosen. For example, in MenuDemo the first menu has the mnemonic A, and its second menu item has the mnemonic B. This means that, when you run MenuDemo with the Java Look & Feel, pressing the Alt and A keys makes the first menu appear. While the first menu is visible, pressing the B key (with or without Alt) makes the second menu item be chosen. A menu item generally displays its mnemonic by underlining the first occurrence of the mnemonic character in the menu item's text, as the following snapshot shows.

An accelerator is a key combination that causes a menu item to be chosen, whether or not it's visible. For example, pressing the Alt and 2 keys in MenuDemo makes the first item in the first menu's submenu be chosen, without bringing up any menus. Only leaf menu items -- menus that don't bring up other menus -- can have accelerators. The following snapshot shows how the Java Look & Feel displays a menu item that has an accelerator. You can specify a mnemonic either when constructing the menu item or with the setMnemonic method. To specify an accelerator, use the setAccelerator method. Here are examples of setting mnemonics and accelerators:
//Setting the mnemonic when constructing a menu item: menuItem = new JMenuItem("A text-only menu item", KeyEvent.VK_T); //Setting the mnemonic after creation time: menuItem.setMnemonic(KeyEvent.VK_T); //Setting the accelerator: menuItem.setAccelerator(KeyStroke.getKeyStroke( KeyEvent.VK_T, ActionEvent.ALT_MASK)); As you can see, you set a mnemonic by specifying the KeyEvent

constant corresponding to the key the user should press. To specify an accelerator you must use a KeyStroke object, which combines a key (specified by a KeyEvent constant) and a modifier-key mask (specified by an ActionEvent constant).

Bringing Up a Popup Menu


To bring up a popup menu ( JPopupMenu ), you must register a mouse listener on each component that the popup menu should be associated with. The mouse listener must detect user requests that the popup menu be brought up. On Windows and Motif platforms, the user brings up a popup menu by pressing the right mouse button while the cursor is over a component that is popup-enabled. The mouse listener brings up the popup menu by invoking the show method on the appropriate JPopupMenu instance. The following code, taken from PopupMenuDemo.java , shows how to create and show popup menus:

//...where instance variables are declared: JPopupMenu popup; //...where the GUI is constructed: //Create the popup menu. popup = new JPopupMenu(); menuItem = new JMenuItem("A popup menu item"); menuItem.addActionListener(this); popup.add(menuItem); menuItem = new JMenuItem("Another popup menu item"); menuItem.addActionListener(this); popup.add(menuItem); //Add listener to components that can bring up popup menus. MouseListener popupListener = new PopupListener(); output.addMouseListener(popupListener); menuBar.addMouseListener(popupListener);

... class PopupListener extends MouseAdapter { public void mousePressed(MouseEvent e) { maybeShowPopup(e); }

public void mouseReleased(MouseEvent e) { maybeShowPopup(e); } private void maybeShowPopup(MouseEvent e) { if (e.isPopupTrigger()) { popup.show(e.getComponent(), e.getX(), e.getY()); } }

Popup menus have a few interesting implementation details. One is that every menu has an associated popup menu. When the menu is activated, it uses its associated popup menu to show its menu items. Another detail is that a popup menu itself uses another component to implement the window containing the menu items. Depending on the circumstances under which the popup menu is displayed, the popup menu might implement its "window" using a lightweight component (such as a JPanel), a "mediumweight" component (such as a Panel ), or a heavyweight window (something that inherits from Window ). Lightweight popup windows are more efficient than heavyweight windows, but they don't work well if you have any heavyweight components inside your GUI. Specifically, when the lightweight popup's display area intersects the heavyweight component's display area, the heavyweight component is drawn on top. This is one of the reasons we recommend against mixing heavyweight and lightweight components. If you absolutely need to use a heavyweight component in your GUI, then you can invoke JPopupMenu.setLightWeightPopupEnabled(false) to disable lightweight popup

windows. For details, see Mixing Heavy and Light Components, an article in The Swing Connection.

Customizing Menu Layout


Because menus are made up of ordinary Swing components, you can easily customize them. For example, you can add any lightweight component to a JMenu or JMenuBar. And because JMenuBar uses BoxLayout, you can customize a menu bar's layout just by adding invisible components to it. Here is an example of adding a glue component to a menu bar, so that the last menu is at the right edge of the menu bar:
//...create and add some menus... menuBar.add(Box.createHorizontalGlue()); //...create the rightmost menu... menuBar.add(rightMenu);

Here is a picture of the result, which you can duplicate by compiling and running MenuGlueDemo.java :

Another way of changing the look of menus is to change the layout managers used to control them. For example, you can change a menu bar's layout manager from the default left-to-right BoxLayout to something such as GridLayout. You can also change how an activated menu or other popup menu lays out its items, as MenuLayoutDemo.java demonstrates. Here's a picture of the menu layout that MenuLayoutDemo creates:

The Menu API


The following tables list the commonly used menu constructors and methods. The API for using menus falls into these categories:

Creating and Setting Up Menu Bars Creating and Populating Menus Creating, Populating, and Controlling Popup Menus Implementing Menu Items Creating and Setting Up Menu Bars Purpose Creates a menu bar. Creates a menu bar.

Constructor or Method
JMenuBar() JMenu add(JMenu)

void setJMenuBar(JMenuBar) JMenuBar getJMenuBar() (in JApplet, JDialog, JFrame, JInternalFrame, JRootPane)

Sets or gets the menu bar of an applet, dialog, frame, internal frame, or root pane.

Constructor or Method
JMenu() JMenu(String) JMenuItem add(JMenuItem) JMenuItem add(Action) JMenuItem add(String) void addSeparator() JMenuItem insert(JMenuItem, int) JMenuItem insert(Action, int) void insert(String, int) void insertSeparator(int) void remove(JMenuItem) void remove(int) void removeAll()

Creating and Populating Menus Purpose Creates a menu. The string specifies the text to display for the menu. Adds a menu item to the current end of the menu. If the argument is an Action object, then the menu creates a menu item as described in How to Use Actions. If the argument is a string, then the menu automatically creates a JMenuItem object that displays the specified text. Adds a separator to the current end of the menu. Inserts a menu item or separator into the menu at the specified position. The first menu item is at position 0, the second at position 1, and so on. The JMenuItem, Action, and String arguments are treated the same as in the corresponding add methods. Removes the specified item(s) from the menu. If the argument is an integer, then it specifies the position of the menu item to be removed.

Creating, Populating, and Controlling Popup Menus Constructor or Method Purpose Creates a popup menu. The optional string argument JPopupMenu() specifies the title that a look and feel might display as JPopupMenu(String) part of the popup window. Adds a menu item to the current end of the popup menu. If the argument is an Action object, then the popup JMenuItem add(JMenuItem) menu creates a menu item as described in How to Use JMenuItem add(Action) Actions. If the argument is a string, then the menu JMenuItem add(String) automatically creates a JMenuItem object that displays the specified text. void addSeparator() Adds a separator to the current end of the popup menu. Inserts a menu item into the menu at the specified position. The first menu item is at position 0, the second void insert(Component, int) at position 1, and so on. The Component argument specifies the menu item to add. void remove(JMenuItem) Removes the specified item(s) from the menu. If the
void remove(int)

argument is an integer, then it specifies the position of the menu item to be removed. By default, Swing implements a menu's window using a lightweight component. This can cause problems if you use any heavyweight components in your Swing static void setLightWeightPopupEnabled(boolean) program, as described in Bringing Up a Popup Menu. (This is one of several reasons to avoid using heavyweight components.) As a workaround, invoke JPopupMenu.setLightWeightPopupEnabled(false).
void removeAll() void show(Component, int, int)

Constructor or Method

JMenuItem() JMenuItem(String) JMenuItem(Icon) JMenuItem(String, Icon) JMenuItem(String, int)

Display the popup menu at the specified X,Y position (specified in that order by the integer arguments) in the coordinate system of the specified component. Implementing Menu Items Purpose Creates an ordinary menu item. The icon argument, if present, specifies the icon that the menu item should display. Similarly, the string argument specifies the text that the menu item should display. The integer argument specifies the keyboard mnemonic to use. You can specify any of the relevant VK constants defined in the KeyEvent class. For example, to specify the A key, use KeyEvent.VK_A. Creates a menu item that looks and acts like a check box. The string argument, if any, specifies the text that the menu item should display. If you specify true for the boolean argument, then the menu item is initially selected (checked). Otherwise, the menu item is initially unselected.

JCheckBoxMenuItem() JCheckBoxMenuItem(String) JCheckBoxMenuItem(Icon) JCheckBoxMenuItem(String, Icon) JCheckBoxMenuItem(String, boolean) JCheckBoxMenuItem(String, Icon, boolean) JRadioButtonMenuItem() JRadioButtonMenuItem(String) JRadioButtonMenuItem(Icon) JRadioButtonMenuItem(String, Icon)

Creates a menu item that looks and acts like a radio button. The string argument, if any, specifies the text that the menu item should JRadioButtonMenuItem(String, display. If you specify true for the boolean boolean) argument, then the menu item is initially JRadioButtonMenuItem(Icon, selected. Otherwise, the menu item is initially boolean) JRadioButtonMenuItem(String, Icon, unselected.
boolean) void setState(boolean) boolean getState() (in JCheckBoxMenuItem) void setEnabled(boolean)

Set or get the selection state of a check box menu item. If the argument is true, enable the menu item.

void setMnemonic(int)

void setAccelerator(KeyStroke) void setActionCommand(String) void addActionListener(ActionListener) void addItemListener(ItemListener)

Otherwise, disable the menu item. Set the mnemonic that enables keyboard navigation to the menu or menu item. Use one of the VK constants defined in the KeyEvent class. Set the accelerator that activates the menu item. Set the name of the action performed by the menu item. Add an event listener to the menu item. See Handling Events from Menu Items for details.

Many of the preceding methods are inherited from AbstractButton. See The Button API for information about other useful methods that AbstractButton provides.

Examples that Use Menus


Menus are used in a few Swing examples. Example Where Described Notes A simple example that creates all kinds of This section (Creating MenuLookDemo menus except popup menus, but doesn't Menus) handle events from the menu items. This section (Handling MenuDemo Adds event handling to MenuLookDemo. Events from Menu Items) This section Demonstrates affecting menu layout by MenuGlueDemo (Customizing Menu adding an invisible components to the menu Layout) bar. This section Implements sideways-opening menus MenuLayoutDemo (Customizing Menu arranged in a vertical menu bar. Layout) Uses Action objects to implement menu ActionDemo How to Use Actions items that duplicate functionality provided by tool bar buttons. Brings up multiple identical frames, each Framework -with a menu in its menu bar. How to Use Internal InternalFrameDemo Uses a menu item to create windows. Frames

How to Use Actions


If you have two or more components that perform the same function, consider using an Action object to implement the function. An Action object is an ActionListener

that provides not only action-event handling, but also centralized handling of the text, icon, and enabled state of tool bar buttons or menu items. By adding an Action to a JToolBar, JMenu, or JPopupMenu, you get the following features:

A new JButton (for JToolBar) or JMenuItem (for JMenu and JPopupMenu) that is automatically added to the tool bar or menu. The button or menu item automatically uses the icon and text specified by the Action. A registered action listener (the Action object) for the button or menu item. Centralized handling of the button or menu item's enabled state.

Here's an example of using an Action to create a tool-bar button and menu item that perform the same function:
Action leftAction = new <a class that implements Action>(...); JButton button = toolBar.add(leftAction); JMenuItem menuItem = mainMenu.add(leftAction);

For a button or menu item to get the full benefit of using an Action, you must create the component using the add(Action) method of JToolBar, JMenu, or JPopupMenu. Currently, no API beyond addActionListener(ActionListener) exists to connect an Action to an already existing component. For example, although you can add an Action object as an action listener to any button, the button won't be notified when the action is disabled. To create an Action object, you generally create a subclass of AbstractAction and then instantiate it. In your subclass, you must implement the actionPerformed method to react appropriately when the action event occurs. Here's an example of creating and instantiating an AbstractAction subclass:
leftAction = new AbstractAction("Go left", new ImageIcon("images/left.gif")) { public void actionPerformed(ActionEvent e) { displayResult("Action for first button/menu item", e); } };

Here's a picture of a demo application that uses actions to implement three features.

Try this: 1. Compile and run the application. The source file is ActionDemo.java . You will also need three image files. See Getting Started with Swing if you need help compiling or running this application. 2. Choose the top item from the left menu (Menu > Go left). The text area displays some text identifying both the event source and the action listener that received the event. 3. Click the leftmost button in the tool bar. The text area again displays information about the event. Note that although the source of the events is different, both events were detected by the same action listener: the Action object with which the components were created. 4. Choose the top item from the Action State menu. This disables the "Go left" Action object, which in turn disables its associated menu item and button. Here is what the user sees when the "Go left" action is disabled:

Here's the code that disables the "Go left" action:


boolean selected = ...//true if the action should be enabled; //false, otherwise leftAction.setEnabled(selected); After you create components using an Action, you might well need to customize

them. For example, you might want to set the tool-tip text for a button. Or you might want to customize the appearance of one of the components by adding or deleting the icon or text. For example, ActionDemo.java has no icons in its menus, no text in its buttons, and tool tips for its buttons. Here's the code that accomplishes this:
button = toolBar.add(leftAction); button.setText(""); //an icon-only button button.setToolTipText("This is the left button"); menuItem = mainMenu.add(leftAction); menuItem.setIcon(null); //arbitrarily chose not to use icon in menu

The Action API

The following tables list the commonly used Action constructors and methods. The API for using Action objects falls into two categories:

Creating and Using an Action Creating an Action-Controlled Component Creating and Using an Action Purpose Create an Action object. Through arguments, you can specify the text and icon to be used in the components that the action controls. Set or get whether the components the action controls are enabled. Invoking setEnabled(false) disables all the components that the action controls. Similarly, invoking Creating an Action-Controlled Component Purpose Create a JMenuItem object and put it in the menu or popup menu. See the discussion in this section and in How to Use Menus for details. Create a JButton object and put it in the tool bar. See the discussion in this section and in How to Use Tool Bars for details.

Constructor or Method
AbstractAction() AbstractAction(String) AbstractAction(String, Icon) void setEnabled(boolean) boolean isEnabled()

setEnabled(true) enables the action's components.

Method
JMenuItem add(Action) JMenuItem insert(Action, int) (in JMenu and JPopupMenu) JButton add(Action) (in JToolBar)

Examples that Use Actions


The following examples use Action objects. Where Example Notes Described Uses actions to bind buttons and menu items to ActionDemo This section the same function. Uses text actions to create menu items for text editing commands, such as cut, copy, and paste, General Rules for and to bind key strokes to caret movement. Also TextComponentDemo Using Text implements custom AbstractAction subclasses Components to implement undo and redo. The text action discussion begins in Concepts: About Editor Kits.
Trail: Creating a GUI with JFC/Swing Lesson: Using Swing Components

General Rules for Using Text Components


is the foundation for Swing's text components, and provides these customizable features for all of its descendants:
JTextComponent

A separate model, known as a document, to manage the component's content. A separate view, which is in charge of displaying the component on screen. A separate controller, known as an editor kit, that can read and write text and that implements editing capabilities with actions . Customizable keymaps and key bindings. Support for infinite undo and redo. Pluggable caret and support for caret change listeners.

This section uses the application shown below to explore each of these capabilities. Although the demo application contains a customized instance of JTextPane, the capabilities discussed in this section are inherited by all of JTextComponent's subclasses.

The upper text component is the customized text pane. The lower text component is an instance of JTextArea, which serves as a log that reports all changes made to the contents of the text pane. The status line at the bottom of the window reports either the location of the selection or the position of the caret, depending on whether text is selected. Try this: 1. Compile and run the application. The source is in TextComponentDemo.java and LimitedStyledDocument.java . See Getting Started with Swing if you need help compiling or running this application.

2. Use the mouse to select text and place the cursor in the text pane. Information about the selection and cursor is displayed at the bottom of the window. 3. Enter text by typing at the keyboard. You can move the caret around using four emacs key bindings: CTRL-B (backward one character), CTRL-F (forward one character), CTRL-N (down one line), and CTRL-P (up one line). 4. Bring up the Edit menu, and use its various menu items to perform editing on the text in the text pane. Make a selection in the text area at the bottom of the window. Because the text area is uneditable, only some of the Edit menu's commands, like copy-to-clipboard, work. It's important to note, though, that the menu operates on both text components. 5. Use the items in the Style menu to apply different styles to the text in the text pane. Using this example application as a reference point, this section covers these topics:

Concepts: About Documents Customizing a Document Listening for Changes on a Document Concepts: About Editor Kits Associating Text Actions with Menus and Buttons Concepts: About Keymaps Associating Text Actions with Keystrokes Implementing Undo and Redo Listening for Caret and Selection Changes

Concepts: About Documents


Like other Swing components, a text component separates its data (known as the model) from its view of the data. If you are not yet familiar with the model-view split used by Swing components, refer to Separate Data and State Models. A text component's model is known as a document and is an instance of a class that implements the Document interface. A document provides these services for a text component:

Contains the text. A document stores the textual content in Element objects, which can represent any logical text structure, such as paragraphs, text runs that share styles, and so on. We do not cover Elements. However, The Swing Connection has at least one article on the subject. Provides support for editing the text through the remove and insertString methods. Notifies document listeners and undoable edit listeners of changes to the text. Manages Position objects, which track a particular location within the text even as the text is modified. Allows you to get information about the text, such as its length, and segments of the text as a string.

The Swing text package contains a subinterface of Document, StyledDocument , that adds support for marking up the text with styles. One JTextComponent subclass, JTextPane, requires that its document be a StyledDocument rather than merely a Document. The javax.swing.text package provides the following hierarchy of document classes, which implement specialized documents for the various JTextComponent subclasses:

A PlainDocument is the default document for text fields, password fields, and text areas. PlainDocument provides a basic container for text where all the text is displayed in the same font. Even though an editor pane is a styled text component, it uses an instance of PlainDocument by default. The default document for a standard JTextPane in an instance of DefaultStyledDocument--a container for styled text in no particular format. However, the document instance used by any particular editor pane or text pane depends on the type of content bound to it. If you use setPage to load text into an editor pane or text pane, the document instance used by the pane might change. Refer to Concepts: Editor Panes and Text Panes for details. Text components inherit the setDocument method, which you can use to dynamically change a component's document. Also most JTextComponent subclasses provide constructors that set the document when creating the component. By replacing a text component's document with one of your own, you can implement certain customizations. For example, the text pane in TextComponentDemo has a custom document that limits the number of characters it can contain.

Customizing a Document
The TextComponentDemo application has a custom document, LimitedStyledDocument , that limits the number of characters that the text pane can contain. LimitedStyledDocument is a subclass of DefaultStyledDocument, the default document for JTextPane. The example needs to use a subclass of DefaultStyledDocument because JTextPane requires its document to be of that type. If you changed the superclass to PlainDocument, the document would work for a text field or text area -- any text component except a text pane. No other code changes would be required, although you would probably remove Styled from the class name, for clarity.

Here's the code from the example program that creates a LimitedStyledDocument and makes it the document for the text pane:
...where the member variables are declared... JTextPane textPane; static final int MAX_CHARACTERS = 300; ...in the constructor for the frame... //Create the document for the text area LimitedStyledDocument lsd = new LimitedStyledDocument(MAX_CHARACTERS); ... //Create the text pane and configure it textPane = new JTextPane(lsd); ... To limit the characters allowed in the document, LimitedStyledDocument overrides its superclass's insertString method, which is called each time text is inserted into the

document. Text insertion can be the result of the user typing or pasting text in, or because of a call to setText. Here is LimitedStyledDocument's implementation of insertString:
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { if ((getLength() + str.length()) <= maxCharacters) super.insertString(offs, str, a); else Toolkit.getDefaultToolkit().beep(); } In addition to insertString, custom documents commonly override the remove

method , which is called each time text is removed from the document. One common use of a custom document is to create a change-validated text field (a field whose value is checked each time its text changes). For two examples of validated text fields, refer to Creating a Validated Text Field.

Listening for Changes on a Document


You can register two different types of listeners on a document: document listeners and undoable edit listeners. This subsection covers document listeners. For information about undoable edit listeners, refer to Implementing Undo and Redo. A document notifies registered document listeners of changes to the document. Use a document listener to react when text is inserted or removed from a document, or when the style of some of the text changes. The TextComponentDemo program uses a document listener to update the change log whenever a change is made to the text pane. The following line of code registers an instance of MyDocumentListener as a listener on the LimitedStyledDocument used in the example:
lsd.addDocumentListener(new MyDocumentListener());

Here's the implementation of MyDocumentListener:


protected class MyDocumentListener implements DocumentListener { public void insertUpdate(DocumentEvent e) { displayEditInfo(e); } public void removeUpdate(DocumentEvent e) { displayEditInfo(e); } public void changedUpdate(DocumentEvent e) { displayEditInfo(e); } private void displayEditInfo(DocumentEvent e) { Document doc = (Document)e.getDocument(); int changeLength = e.getLength(); changeLog.append(e.getType().toString() + ": " + changeLength + " character" + ((changeLength == 1) ? ". " : "s. ") + " Text length = " + doc.getLength() + "." + newline); } }

The listener implements three methods for handling three different types of document events: insertion, removal, and style changes. StyledDocuments can fire all three types of events. PlainDocuments fire events only for insertion and removal. For general information about document listeners and document events, see How to Write a Document Listener. Remember that the document for this text pane limits the number of characters allowed in the document. If you try to add more text than the document allows, the document blocks the change and the listener's insertUpdate method is not called. Document listeners are notified of changes only if the change has already occurred. Sometimes, you might be tempted to change the document's text from within a document listener. For example, if you have a text field that should contain only integers and the user enters some other type of data, you might want to change the text to 0. However, you should never modify the contents of text component from within a document listener. In fact, if you do, your program will likely deadlock! Instead, provide a custom document and override the insertString and remove methods as needed.

Concepts: About Editor Kits


All Swing text components supports standard editing commands such as cut, copy, paste, and inserting characters. Each editing command is represented and implemented by an Action object. Actions makes it easy for you to associate a command with a GUI component, such as a menu item or button, and therefore build a GUI around a text component. Under the hood, text components use an EditorKit to create and manage actions. Besides managing a set of actions for a text component, an editor kit also knows how to read and write documents of a particular format. Although all text components use editor

kits, some components hide theirs. You can't set or get the editor kit used by a text field, password field, or text area. Editor panes and text panes provide the getEditorKit method to get the current editor kit and the setEditorKit to change it. For all components, JTextComponent provides API for you to indirectly invoke or customize some editor kit capabilities. For example, JTextComponent provides read and write methods, which invoke the editor kit's read and write methods. JTextComponent also provides a method, getActions, which returns all of the actions supported by a component. The Swing text package provides these editor kits:
DefaultEditorKit

StyledEditorKit

Reads and writes plain text. Provides a basic set of editing commands. All the other editor kits are descendants of this one. Reads and writes styled text and provides a minimal set of actions for styled text. This class is a subclass of DefaultEditorKit and is the editor kit used by JTextPane by default.

HTMLEditorKit RTFEditorKit

Reads, writes, and edits HTML. This is a subclass of StyledEditorKit.

Reads, writes, and edits RTF. This is a subclass of StyledEditorKit. Each of the editor kits above has been registered with the JEditorPane class and associated with the text format that the kit reads, writes, and edits. When a file is loaded into an editor pane, the pane checks the format of the file against its registered kits. If a registered kit is found that supports that file format, the pane uses the kit to read the file, display, and edit it. Thus, the editor pane effectively transforms itself into an editor for that text format. You can extend JEditorPane to support your own text format by creating an editor kit for it, and then using JEditorPane's registerEditorKitForContentType to associate your kit with your text format.

Associating Text Actions with Menus and Buttons


As we mentioned before, you can call the getActions method on any text component to get an array containing all of the actions supported by it. Often it's convenient to load the array of actions into a Hashtable so your program can retrieve an action by name. Here's the code from TextComponentDemo that gets the actions from the text pane and loads them into a Hashtable:
private void createActionTable(JTextComponent textComponent) { actions = new Hashtable(); Action[] actionsArray = textComponent.getActions(); for (int i = 0; i < actionsArray.length; i++) { Action a = actionsArray[i]; actions.put(a.getValue(Action.NAME), a); } }

And here's a convenient method for retrieving an action by its name from the hashtable:

private Action getActionByName(String name) { return (Action)(actions.get(name)); }

You can use both methods verbatim in your programs. Now let's look at how the Cut menu item is created and associated with the action of removing text from the text component:
protected JMenu createEditMenu() { JMenu menu = new JMenu("Edit"); ... menu.add(getActionByName(DefaultEditorKit.cutAction)); ...

This code gets the action by name using the handy method shown previously. It then adds the action to the menu. That's all you need to do. The menu and the action take care of everything else. You'll note that the name of the action comes from DefaultEditorKit . This kit provides actions for basic text editing and is the superclass for all the editor kits provided by Swing. So its capabilities are available to all text components unless overridden by a customization. For efficiency, text components share actions. The Action object returned by getActionByName(DefaultEditorKit.cutAction) is shared by the uneditable JTextArea at the bottom of the window. This has two important ramifications:

Generally speaking, you shouldn't modify Action objects you get from editor kits. If you do, the changes affect all text components in your program. Action objects can operate on other text components in the program, perhaps more than you intended. In this example, even though it's uneditable, the JTextArea shares actions with the JTextPane. (Select some text in the text area, then choose the cut-to-clipboard menu item. You'll hear a beep because the text area is uneditable.) If you don't want to share, consider instantiating the Action object yourself. DefaultEditorKit defines a number of useful Action subclasses.

Here's the code that creates the Style menu and puts the Bold menu item in it:
protected JMenu createStyleMenu() { JMenu menu = new JMenu("Style"); Action action = new StyledEditorKit.BoldAction(); action.putValue(Action.NAME, "Bold"); menu.add(action); ... StyledEditorKit provides Action subclasses to implement editing

The commands for styled text. You'll note that instead of getting the action from the editor kit, this code creates an instance of the BoldAction class. Thus, this action is not shared with any other text component, and changing its name won't affect any other text component. In addition to associating an action with a GUI component, you can also associate an action with a keystroke. Associating Text Actions with Keystrokes shows you how.

Concepts: About Keymaps


This section assumes that you understand actions and how to get them from the editor kit. If you don't, read Concepts: About Editor Kits and Associating Text Actions with Menus and Buttons. Every text component has one or more Keymap objects. A keymap contains a collection of name-value pairs where the name is a KeyStroke and the value is an Action. Each pair binds the keystroke to the action such that when the user types the keystroke, the action occurs. By default, a text component has one keymap named JTextComponent.DEFAULT_KEYMAP. This keymap contains standard, basic key bindings. For example, the arrow keys are mapped to caret movement, and so on. You can enhance or modify the default keymap in the following ways:

Add a custom keymap to the text component with JTextComponent's addKeymap method. Add key bindings to the default keymap with Keymap's addActionForKeyStroke method. The default keymap is shared among text components, so use this with caution. Remove key bindings from the default keymap with Keymap's removeKeyStrokeBinding method. The default keymap is shared among text components, so again, use this with caution.

When resolving a keystroke to its action, the text component checks the keymaps in the order they are added to the text component. Thus, the binding for a specific keystroke in a keymap that you add to a text component overrides any binding for the same keystroke in the default keymap.

Associating Text Actions with Keystrokes


The text pane in the TextComponentDemo supports four key bindings not provided by the default keymap.
CTRL-B CTRL-F CTRL-N CTRL-P

for moving the caret backward one character for moving the caret forward one character for moving the caret down one line for moving the caret up one line

The following code adds a new keymap to the text pane and adds the CTRL-B key binding to it. The code for adding the other three is similar.
Keymap keymap = textPane.addKeymap("MyEmacsBindings", textPane.getKeymap()); Action action = getActionByName(DefaultEditorKit.backwardAction); KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_B,

Event.CTRL_MASK); keymap.addActionForKeyStroke(key, action); The code first adds a keymap to the component's hierarchy. The addKeymap

method creates the keymap for you with the name and parent provided in the method call. In the example, the parent is the text pane's default keymap. Next, the code gets the backward action from the editor kit and gets a KeyStroke object representing the CTRL-B key sequence. Finally, the code adds the action and keystroke pair to the keymap, thereby binding the key to the action.

Implementing Undo and Redo


Note: The implementation of undo and redo in TextComponentDemo was taken from the NotePad demo that comes with the JFC 1.1 and JDK 1.2 releases. Many programmers will also be able to copy this implementation of undo/redo without modification. Implementing undo and redo has two parts:

Remembering the undoable edits that occur. Implementing the undo and redo commands and providing a user interface for them.

Part 1: Remembering Undoable Edits To support undo and redo, a text component must remember each edit that occurs, the order of edits, and what it takes to undo each edit. The example program uses an instance of the UndoManager class to manage its list of undoable edits. The undo manager is created where the member variables are declared:
protected UndoManager undo = new UndoManager();

Now, let's look at how the program finds out about undoable edits and adds them to the undo manager. A document notifies interested listeners whenever an undoable edit occurs on its content. An important step in implementing undo and redo is to register an undoable edit listener on the document of the text component. The following code adds an instance of MyUndoableEditListener to the text pane's document:
lsd.addUndoableEditListener(new MyUndoableEditListener());

The undoable edit listener used in our example adds the edit to the undo manager's list:
protected class MyUndoableEditListener implements UndoableEditListener { public void undoableEditHappened(UndoableEditEvent e) { //Remember the edit and update the menus undo.addEdit(e.getEdit()); undoAction.updateUndoState(); redoAction.updateRedoState(); } }

Note that this method updates two objects: undoAction and redoAction. These are the action objects attached to the Undo and Redo menu items, respectively. The next step shows you how the menu items are created and the implementation of the two actions. For general information about undoable edit listeners and undoable edit events, see How to Write an Undoable Edit Listener. Part 2: Implementing the Undo and Redo Commands The first step in this part of implementing undo and redo is to create the actions to put in the Edit menu.
JMenu menu = new JMenu("Edit"); //Undo and redo are actions of our own creation undoAction = new UndoAction(); menu.add(undoAction); redoAction = new RedoAction(); menu.add(redoAction); ...

The undo and redo actions are implemented by custom AbstractAction subclasses: UndoAction and RedoAction, respectively. These classes are inner classes of the example's primary class. When the user invokes the Undo command, UndoAction's actionPerformed method, shown here, gets called:
public void actionPerformed(ActionEvent e) { try { undo.undo(); } catch (CannotUndoException ex) { System.out.println("Unable to undo: " + ex); ex.printStackTrace(); } updateUndoState(); redoAction.updateRedoState(); } This method calls the undo manager's undo method and updates the

menu items to reflect

the new undo/redo state. Similarly, when the user invokes the Redo command, the actionPerformed method in RedoAction gets called:
public void actionPerformed(ActionEvent e) { try { undo.redo(); } catch (CannotRedoException ex) { System.out.println("Unable to redo: " + ex); ex.printStackTrace(); } updateRedoState(); undoAction.updateUndoState();

This method is similar except that it calls the undo manager's redo method. Much of the code in the UndoAction and RedoAction classes is dedicated to enabling and disabling the actions as appropriate for the current state, and changing the names of the menu items to reflect the edit to be undone or redone.

Listening for Caret and Selection Changes


The TextComponentDemo program uses a caret listener to display the current position of the caret or, if text is selected, the extent of the selection. The caret listener class in this example is a JLabel subclass. Here's the code that creates the caret listener label and makes it a caret listener of the text pane:
//Create the status area CaretListenerLabel caretListenerLabel = new CaretListenerLabel( "Caret Status"); ... textPane.addCaretListener(caretListenerLabel); A caret listener must implement one method, caretUpdate, which is called each time the caret moves or the selection changes. Here's the CaretListenerLabel implementation of caretUpdate: public void caretUpdate(CaretEvent e) { //Get the location in the text int dot = e.getDot(); int mark = e.getMark(); if (dot == mark) { // no selection try { Rectangle caretCoords = textPane.modelToView(dot); //Convert it to view coordinates setText("caret: text position: " + dot + ", view location = [" + caretCoords.x + ", " + caretCoords.y + "]" + newline); } catch (BadLocationException ble) { setText("caret: text position: " + dot + newline); } } else if (dot < mark) { setText("selection from: " + dot + " to " + mark + newline); } else { setText("selection from: " + mark + " to " + dot + newline); } }

As you can see, this listener updates its text label to reflect the current state of the caret or selection. The listener gets the information to display from the caret event object. For general information about caret listeners and caret events, see How to Write a Caret Listener.

As with document listeners, a caret listener is passive. It reacts to changes in the caret or in the selection but does not change the caret or the selection. If you want to change the caret or selection, then you should use a custom caret instead. To create a custom caret, write a class that implements the Caret interface, then provide an instance of your class as an argument to setCaret on a text component.

How to Write a Caret Listener


Caret events occur when the caret in a text component moves or when the selection in a text component changes. You can attach a caret listener to an instance of any JTextComponent subclass with the addCaretListener method. If your program has a custom caret, you might find it more convenient to attach a listener to the caret object rather than to the text component for which it is a caret. A caret fires change events rather than caret events, so you would need to write a change listener rather than a caret listener. Here is the caret event handling code from an application called TextComponentDemo.
... //where initialization occurs CaretListenerLabel caretListenerLabel = new CaretListenerLabel("Caret Status"); ... textPane.addActionListener(caretListenerLabel); ... protected class CaretListenerLabel extends JLabel implements CaretListener { ... public void caretUpdate(CaretEvent e) { //Get the location in the text int dot = e.getDot(); int mark = e.getMark(); ... } }

You can find the full source code for the program and instructions for compiling and running it in General Rules for Using Text Components . For a discussion about the caret listener aspect of the program see Listening for Caret and Selection Changes .

The Caret Event API


The CaretListener interface has just one method, so it has no corresponding adapter class. Here's the method:
void caretUpdate(CaretEvent)

Called when the caret in the listened-to component moves or when the selection in the listened-to component changes. The caretUpdate method has a single parameter: a CaretEvent object. To get the text component that fired the event, use the getSource method which CaretEvent inherits from EventObject . The CaretEvent class defines two useful methods:
int getDot()

int getMark()

Returns the current location of the caret. If text is selected, the caret marks one end of the selection. Returns the other end of the selection. If nothing is selected, the value returned by this method is equal to the value returned by getDot. Note that the dot is not guaranteed to be less than the mark.

Examples that Use Caret Listeners


The following table lists the examples that use caret listeners. Example Where Described Notes Listening for Caret and Uses a "listener label" to display caret TextComponentDemo Selection Changes and selection status.
Trail: Creating a GUI with JFC/Swing Lesson: Using Swing Components

The JComponent Class


With the exception of top-level containers, all Swing components whose names begin with "J" descend from the JComponent class. For example, JPanel, JScrollPane, JButton, and JTable all inherit from JComponent. However, JFrame doesn't because it implements a top-level container. Note: A few Swing components aren't top-level containers and yet don't inherit from JComponent. The one you're most likely to need is the Box.Filler class, which is a nonpainting component designed for use with BoxLayout . The Box.Filler class doesn't inherit from JComponent because it is so specialized that it needs no JComponent features, and because it is instantiated so often that it should be as small and fast as possible. The JComponent class extends the Container class, which itself extends Component . The Component class includes everything from providing layout hints to supporting painting and events. The Container class has support for adding components to the container and laying them out. This section's API tables summarize the most often used methods of Component and Container. Information about how to use the methods is scattered throughout this trail.

JComponent Features
The JComponent class provides the following functionality to its descendants:

Tool tips Borders Keyboard-generated actions Application-wide pluggable look and feel Properties Support for layout Support for accessibility Double buffering Methods to increase efficiency

Tool tips By specifying a string with the setToolTipText method, you can provide help to users of a component. When the cursor pauses over the component, the specified string is displayed in a small window that appears near the component. See How to Use Tool Tips for more information. Borders The setBorder method allows you to specify the border that a component displays around its edges. See How to Use Borders for details. Keyboard-generated actions Using the registerKeyboardAction method, you can enable the user to use the keyboard, instead of the mouse, to operate the GUI. Note: Some classes provide convenience methods for keyboard actions. For example, AbstractButton provides setMnemonic, which lets you specify the key that, in combination with a look-and-feel-specific modifier key, causes the button's action to be performed. See How to Use Buttons, Check Boxes, and Radio Buttons for an example of using mnemonics in buttons. The combination of character and modifier keys that the user must press to start an action is represented by a KeyStroke object. The resulting action event must be handled by an action listener . Each keyboard action works under exactly one of three conditions: only when the actual component has the focus, only when the component or one of its containers has the focus, or any time that anything in the component's window has the focus. Application-wide pluggable look and feel Behind the scenes, each JComponent object has a corresponding ComponentUI object that performs all the drawing, event handling, size determination, and so on for that JComponent. Exactly which ComponentUI object is used depends on the current look and feel, which you can set using the UIManager.setLookAndFeel method. See How to Set the Look and Feel for details. Properties You can associate one or more properties (name/object pairs) with any JComponent. For example, a layout manager might use properties to associate a constraints object with each JComponent it manages. You put and get properties

using the putClientProperty and getClientProperty methods. For general information about properties, see Using Properties to Manage Program Attributes . Support for layout Although the Component class provides layout hint methods such as getPreferredSize and getAlignmentX, it doesn't provide any way to set these layout hints, short of creating a subclass and overriding the methods. To give you another way to set layout hints, the JComponent class adds setter methods -setPreferredSize, setMinimumSize, setMaximumSize, setAlignmentX, and setAlignmentY. See Layout Management for more information. Support for accessibility The JComponent class provides API and basic functionality to help assistive technologies such as screen readers get information from Swing components, For more information about accessibility, see How to Support Assistive Technologies . Double buffering Double buffering smooths on-screen painting. For details, see Painting . Methods to increase efficiency JComponent has a few methods that provide more efficient ways to get information than the JDK 1.1 API allowed. The methods include getX and getY, which you can use instead of getLocation; and getWidth and getHeight, which you can use instead of getSize. It also adds one-argument forms of getBounds, getLocation, and getSize for which you specify the object to be modified and returned, letting you avoid unnecessary object creation. These methods have been added to Component for Java 2 (JDK 1.2).

The JComponent API


The JComponent class provides many new methods and inherits many methods from Component and Container. The following tables summarize the methods we use the most. The table is for reference only. Wherever possible, we provide links to where the API is discussed in more detail.

Customizing Component Appearance Setting Component State Handling Events Painting Components Dealing with the Containment Hierarchy Laying Out Components Getting Size and Position Information Specifying Absolute Size and Position

Customizing Component Appearance Method Purpose void setBorder(Border) Set or get the border of the component. See How to Use

Border getBorder() (in JComponent) void setForeground(Color) Color getForeground() void setBackground(Color) Color getBackground() (in java.awt.Component) void setOpaque(boolean) (in JComponent) boolean isOpaque (in JComponent) void setFont(Font) Font getFont() (in java.awt.Component) FontMetrics getFontMetrics(Font) (in java.awt.Component)

Borders for details. Set or get the foreground or background color for the component. The foreground is generally the color used to draw the text in a component. The background is (not surprisingly) the color of the background areas of the component, assuming that the component is opaque. Set whether the component is opaque. An opaque component fills its background with its background color. Get whether the component is opaque. This method (but not setOpaque) was added to Component in 1.2. Set or get the component's font. If a font has not been set for the component, the font of its parent is returned. Get the font metrics for the specified font. Setting Component State Purpose Set the text to display in a tool tip. See How to Use Tool Tips for more information. Set or get whether the component is enabled. An enabled component can respond to user input and generate events. Set or get the component's locale. If the component does not have a locale, the locale of its parent is returned. See Internationalization for information about locales. Set or get the cursor image to display when the mouse is over the component. Set or get whether the component is visible. Components are initially visible, with the exception of top-level components.

Method
void setToolTipText(String) (in JComponent) void setEnabled(boolean b) boolean isEnabled() (in java.awt.Component) void setLocale(Locale l) Locale getLocale() (in java.awt.Component) void setCursor(Cursor) Cursor getCursor() (in java.awt.Component) void setVisible(boolean) boolean isVisible() (in java.awt.Component)

Handling Events (see Event Handling for details) Method Purpose void addComponentListener(ComponentListener) Add or remove a component void listener to or from the
removeComponentListener(ComponentListener)

component. Component listeners are notified when the (in java.awt.Component) listened-to component is hidden, shown, moved, or resized. Add or remove a key listener to or from the component. Key void addKeyListener(KeyListener) listeners are notified when the void removeKeyListener(KeyListener l) user types at the keyboard and (in java.awt.Component) the listened-to component has the keyboard focus. Add or remove a mouse listener to or from the component. addMouseListener(MouseListener l) Mouse listeners are notified void removeMouseListener(MouseListener) when the user uses the mouse to (in java.awt.Component) interact with the listened-to component. Add or remove a mouse motion void listener to or from the addMouseMotionListener(MouseMotionListener) component. Mouse motion void removeMouseMotionListener(MouseMotionListener) listeners are notified when the user moves the mouse within the listened-to component's (in java.awt.Component) bounds. Add or remove a container listener to or from the void addContainerListener(ContainerListener) void container. Container listeners removeContainerListener(ContainerListener) are notified when a component (in java.awt.Container) is added to or removed from the listened-to container. Add or remove a focus listener void addFocusListener(FocusListener) to or from the component. void removeFocusListener(FocusListener) Focus listeners are notified (in java.awt.Component) when the listened-to component gains or loses keyboard focus. Set or get the next focusable Component getNextFocusableComponent() component. null indicates that void setNextFocusableComponent(Component) the focus manager should (in JComponent) choose the next focusable component automatically. void requestFocus() Request that the component get boolean hasFocus() the keyboard focus, or detect (in java.awt.Component) whether it has the focus. boolean contains(int, int) Determine whether the

boolean contains(Point p) (in java.awt.Component)

Component getComponentAt(int, int) (in java.awt.Container)

specified point is within the component. The argument should be specified in terms of the component's coordinate system. The two int arguments specify x and y coordinates, respectively. Return the component that contains the specified x, y position. The top-most child component is returned in the case where components overlap. This is determined by finding the component closest to the index 0 that claims to contain the given point via Component.contains().

Method
void repaint() void repaint(int, int, int, int) (in java.awt.Component) void repaint(Rectangle) (in JComponent)

Painting Components (see Painting for details) Purpose Request that all or part of the component be repainted. The four int arguments specify the bounds (x, y, width, height, in that order) of the rectangle to be painted. Request that the specified area within the component be repainted. Request that the component and its affected containers be laid out again. You shouldn't generally need to invoke this method unless you explicitly change a component's size/alignment hints after it's visible, change a containment hierarchy after it's visible, or perhaps change the data in a component's model directly (without going through the component's API). You might need to invoke repaint after revalidate. Paint the component. Override this method to implement painting for custom components.

void revalidate() (in JComponent)

void paintComponent(Graphics) (in JComponent)

Dealing with the Containment Hierarchy (see Swing Components and the Containment Hierarchy for more information) Method Purpose Component Add the specified component to the container. The oneadd(Component) argument version of this method adds the component to the end Component of the container. When present, the int argument indicates the add(Component, int) new component's position within the container. When present, void add(Component,

Object)

(in
java.awt.Container) void remove(int) void remove(Component comp) void removeAll()

the Object argument provides layout constraints to the current layout manager. Remove one of or all of the components from the container. When present, the int argument indicates the position within the container of the component to remove.

(in
java.awt.Container) JRootPane getRootPane() (in JComponent) Container getParent()

Get the root pane ancestor for the component.

(in
java.awt.Component) int getComponentCount()

Get the component's parent.

(in
java.awt.Container) Component getComponent(int) Component[] getComponents()

Get the number of components in the container.

(in
java.awt.Container)

Get the one of or all of the components in the container. The int argument indicates the position of the component to get.

Laying Out Components (see Laying Out Components Within a Container for more information) Method Purpose void Set the component's preferred, maximum, or minimum setPreferredSize(Dimension) size, measured in pixels. The preferred size indicates void the best size for the component. The component should setMaximumSize(Dimension) be no larger than its maximum size and no smaller than void setMinimumSize(Dimension) its minimum size. Be aware that these are hints only (in JComponent) and might be ignored by certain layout managers. Get the preferred, maximum, or minimum size of the Dimension getPreferredSize() component, measured in pixels. For non-JComponent subclasses, which don't have the corresponding setter Dimension getMaximumSize() methods, you can set a component's preferred, Dimension getMinimumSize() maximum, or minimum size by creating a subclass and (in java.awt.Component) overriding these methods. void setAlignmentX(float) Set the alignment along the x or y axis. These values void setAlignmentY(float) indicate how the component would like to be aligned (in JComponent) relative to other components. The value should be a number between 0 and 1 where 0 represents alignment

float getAlignmentX() float getAlignmentY() (in java.awt.Component) void setLayout(LayoutManager) LayoutManager getLayout() (in java.awt.Container)

along the origin, 1 is aligned the furthest away from the origin, and 0.5 is centered, and so on. Be aware that these are hints only and might be ignored by certain layout managers. Get the preferred, maximum, or minimum size of the component. For non-Swing components, which don't have the corresponding setter methods, you can set a component's preferred, maximum, or minimum size by creating a subclass and overriding these methods. Set or get the component's layout manager. The layout manager is responsible for sizing and positioning the components within a container.

Method

Getting Size and Position Information Purpose Get the current width or height of the component measured in pixels. Get the component's current size measured in pixels. When using the one-argument version of this method, the caller is responsible for creating the Dimension instance in which the result is returned. Get the current x or y coordinate of the component's origin relative to the parent's upper left corner measured in pixels. Get the bounds of the component measured in pixels. The bounds specify the component's width, height, and origin relative to its parent. When using the one-argument version of this method, the caller is responsible for creating the Rectangle instance in which the result is returned. Gets the current location of the component relative to the parent's upper left corner measured in pixels. When using the one-argument version of getLocation method, the caller is responsible for creating the Point instance in which the result is returned. The getLocationOnScreen method returns the position relative to the upper left corner of the screen. Get the insets of the component.

int getWidth() int getHeight() (in java.awt.Component) Dimension getSize() Dimension getSize(Dimension) (in java.awt.Component) int getX() int getY() (in java.awt.Component) Rectangle getBounds() Rectangle getBounds(Rectangle) (in java.awt.Component) Point getLocation() Point getLocation(Point) Point getLocationOnScreen() (in java.awt.Component) Insets getInsets() (in java.awt.Container)

Specifying Absolute Size and Position (see Doing Without a Layout Manager (Absolute Positioning) for more information) Method Purpose void setLocation(int, Set the location of the component, in pixels, relative to the int) parent's upper left corner. The two int arguments specify x void setLocation(Point)

(in java.awt.Component)

and y, in that order. Use these methods to position a component when you aren't using layout manager.

void setSize(int, int) Set the size of the component measured in pixels. The two void setSize(Dimension) int arguments specify width and height, in that order. Use

(in java.awt.Component)
void setBounds(int, int, int, int) void setBounds(Rectangle) (in java.awt.Component)

these methods to size a component when you aren't using layout manager. Set the size and location relative to the parent's upper left corner, in pixels, of the component. The four int arguments specify x, y, width, and height, in that order. Use these methods to position and size a component when you aren't using layout manager.

Trail: Creating a GUI with JFC/Swing Lesson: Using Swing Components

How to Use Text Fields


A text field is a basic text control that lets the user enter a small amount of text. When the user indicates that text entry is complete (usually by pressing Return), the text field fires an action event . Generally you use the JTextField class to provide text fields. If you need to provide a password field -- an editable text field that doesn't show the characters the user types -- use the JPasswordField class instead. This section discusses both text fields and password fields. If you want a text field that also provides a menu of strings to choose from, consider using an editable combo box. If you need to obtain more than one line of input from the user, then you should use one of the classes that implements a general-purpose text area. The applet below displays a basic text field and a text area. The text field is editable; the text area isn't. When the user presses Return in the text field, the applet copies the text field's contents to the text area, and then selects all the text in the text field.

This is a picture of the applet's GUI. To run the applet, click the picture. The applet will appear in a new browser window.

You can find the source for the program in TextDemo.java . Here's the code from TextDemo that creates the text field in the applet:
textField = new JTextField(20); textField.addActionListener(this); ... contentPane.add(textField); The integer argument passed to the JTextField

constructor, 20 in the example, indicates the number of columns in the field. This number is used along with metrics provided by the field's current font to calculate the field's preferred width. It does not limit the number of characters the user can enter. To do that, you need to implement a custom document, as described in General Rules for Using Text Components. The next lines of code register the applet as an action listener for the text field and add the text field to the applet's content pane. Here's the actionPerformed method that handles action events from the text field:
public void actionPerformed(ActionEvent evt) { String text = textField.getText(); textArea.append(text + newline); textField.selectAll(); } Notice the use of JTextField's getText method to retrieve

the text currently contained by the text field. The text returned by this method does not include a newline character for the Return key that fired the action event. This example illustrates using a basic, off-the-shelf text field for entering textual data and performing a task when the text field fires an action event. This is sufficient for many programs. Other programs, however, need more advanced behavior. As a subclass of JTextComponent , JTextField can be configured and customized. One common customization is to provide a text field whose contents are validated. This section covers the following advanced text field topics. To get most out of the information, you need to understand the material presented in the previous section, General Rules for Using Text Components.

Creating a Validated Text Field Using a Document Listener on a Text Field Laying Out Label-Text Field Pairs Providing a Password Field The Text Field and Password Field API Examples that Use Text Fields and Password Fields

Creating a Validated Text Field


Many programs require users to enter textual data of a certain type or format. For example, a program might provide a text field for entering a date, a decimal number, or a

phone number. The contents of such a text field must be validated before being used for any purpose. A text field can be action-validated or change-validated. The data in an action-validated field is checked each time the field fires an action event (each time the user presses the Return key). An action-validated field might, at any given point in time, contain invalid data. However, the data is validated before it's used for anything. To create an action-validated field, provide an action listener for your field and implement its actionPerformed method as follows:

Use getText to get the contents of the text field, or getPassword if you're using a password field. Evaluate the value returned. If the value is valid, do whatever task or calculation is required. If the value is invalid, report an error and return without performing a task or calculation. described later in this section, action-validates a password field in this

PasswordDemo,

manner. The data in a change-validated field is checked each time the field changes. A field that is change-validated can never contain invalid data because every change (keystroke, cut, copy, and so on) that might cause the data to be invalid is rejected. To create a changevalidated text field you need to provide a custom document for your text field. If you aren't familiar with documents yet, see Concepts: About Documents. Warning: Do not use a document listener for change validation. By the time a document listener has been notified of a change, it's too late, the change has already taken place. See the last couple of paragraphs in Listening for Changes on a Document for more information. The application shown in the following figure has three change-validated text fields. The user enters loan information into the first three text fields. Each time the user types a character, the program validates the input and updates the result in the fourth text field.

Try this: 1. Compile and run the application. The source file is TextFieldDemo.java . You will also need WholeNumberField.java , DecimalField.java , and FormattedDocument.java . See Getting Started with Swing if you need help compiling or running this application.

2. Enter information into the text fields and see the results. If you attempt to enter invalid data, the program beeps. 3. Try to type into the fourth text field. You can't because it isn't editable. However, you can select the text. 4. Resize the window. Note how the labels and text fields remain aligned. Laying Out Label-Text Field Pairs talks more about this feature of the program. The Years field is an instance of WholeNumberField , which is a subclass of JTextField. By overriding the createDefaultModel method, WholeNumberField establishes a custom Document subclass -- an instance of WholeNumberDocument -- as the document for each WholeNumberField created:
protected Document createDefaultModel() { return new WholeNumberDocument(); } Here's the implementation of WholeNumberDocument: protected class WholeNumberDocument extends PlainDocument {

public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { char[] source = str.toCharArray(); char[] result = new char[source.length]; int j = 0; for (int i = 0; i < result.length; i++) { if (Character.isDigit(source[i])) result[j++] = source[i]; else { toolkit.beep(); System.err.println("insertString: " + source[i]); } } super.insertString(offs, new String(result, 0, j), a); } }

This class overrides the insertString method, which is called every time any string or character is about to be inserted into the document. WholeNumberDocument's implementation of insertString evaluates each character to be inserted into the text field. If the character is a digit, the document allows it to be inserted. Otherwise, the method beeps and prints an error message. Thus WholeNumberDocument allows the numbers in the range 0, 1, 2, ... An interesting implementation detail is that our custom document class does not have to override the remove method. The remove method is called each time a character or group of characters is removed from the text field. Because removing a digit from an integer cannot produce an invalid result, this class does not pay attention to removals. The other two input fields in the example, as well as the uneditable Monthly Payment field, are all instances of DecimalField , a custom JTextField subclass.

uses a custom document, FormattedDocument , that allows only data of a particular format to be entered.
DecimalField

has no knowledge of the actual format of its content. Instead, relies on a format, an instance of a subclass of Format , to accept or reject a proposed change. The text field that uses the FormattedDocument must specify which format the FormattedDocument uses.
FormattedDocument FormattedDocument

The Loan Amount and Monthly Payment text fields use a NumberFormat object created like this:
moneyFormat = NumberFormat.getNumberInstance();

The following code creates the APR text field's format:

percentFormat = NumberFormat.getNumberInstance(); percentFormat.setMinimumFractionDigits(3); As the code shows, the same class (NumberFormat) can support different formats. Furthermore, Format and its subclasses are locale-sensitive, so a decimal field can

be made to support formats for specific countries and regions. Refer to Formatting in the internationalization trail for detailed information about formats. Here is FormattedDocument's implementation of insertString:
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { String currentText = getText(0, getLength()); String beforeOffset = currentText.substring(0, offs); String afterOffset = currentText.substring(offs, currentText.length()); String proposedResult = beforeOffset + str + afterOffset; try { format.parseObject(proposedResult); super.insertString(offs, str, a); } catch (ParseException e) { Toolkit.getDefaultToolkit().beep(); System.err.println("insertString: could not parse: " + proposedResult); } }

The method uses the format to parse the result of the proposed insertion. If the result is properly formatted, this method calls its superclass's insert method to do the insertion. If the result is not properly formatted, the program beeps. In addition to overriding insertString, FormattedDocument also overrides the remove method. Recall that the remove method is called each time a character or group of characters is to be removed from the document.
public void remove(int offs, int len) throws BadLocationException

String currentText = getText(0, getLength()); String beforeOffset = currentText.substring(0, offs); String afterOffset = currentText.substring(len + offs, currentText.length()); String proposedResult = beforeOffset + afterOffset; try { if (proposedResult.length() != 0) format.parseObject(proposedResult); super.remove(offs, len); } catch (ParseException e) { Toolkit.getDefaultToolkit().beep(); System.err.println("remove: could not parse: " + proposedResult); }

The FormattedDocument implementation of the remove method is similar to its implementation of the insertString method. The format parses the result of the proposed change and performs the removal or not, depending on whether the result is valid. Note: The solution provided by this example is not a general solution for all types of formats. Some formats -- most notably DateFormat -- can't be change-validated simply by calling the parseObject method. Here's an example to help you understand why. Suppose you have a text field that contains the date "May 25, 1996" and want to change it to "June 11, 1996". You would select May and begin typing "June". As soon as you've typed the "J", the field won't parse because "J 25, 1996" is not a valid date even though it's a valid change. A number of solutions are possible for dates and other types of data where a partially completed change creates an invalid result. You can change the changevalidation such that it rejects all definitely invalid changes (typing "X" into a date for example) but allows all possibly valid changes. Or you can switch to an action-validated field.

Using a Document Listener on a Text Field


If you can't use a document listener for field validation, what can you use it for? Use it to listen to, but not interfere with, changes to the document's content. The loan calculator uses the following document listener to update the monthly payment after every change:
class MyDocumentListener implements DocumentListener { public void insertUpdate(DocumentEvent e) { calculateValue(e); } public void removeUpdate(DocumentEvent e) { calculateValue(e); } public void changedUpdate(DocumentEvent e) { // we won't ever get this with a PlainDocument } private void calculateValue(DocumentEvent e) { Document whatsup = e.getDocument(); if (whatsup.getProperty("name").equals("amount"))

} }

amount = amountField.getValue(); else if (whatsup.getProperty("name").equals("rate")) rate = rateField.getValue(); else if (whatsup.getProperty("name").equals("numPeriods")) numPeriods = numPeriodsField.getValue(); payment = computePayment(amount, rate, numPeriods); paymentField.setValue(payment);

This is an appropriate use of a document listener. For general information about document listeners, see Listening for Changes on a Document and How to Write a Document Listener .

Laying Out Label-Text Field Pairs


This section describes how the label and the text fields in the example are aligned and requires some knowledge of layout managers. Rows of label and text field pairs such as those found in the loan calculator are quite common on preference panels and panels that implement forms. Here's the code that lays out the label and text field pairs.
. . . //Layout the labels in a panel JPanel labelPane = new JPanel(); labelPane.setLayout(new GridLayout(0, 1)); labelPane.add(amountLabel); labelPane.add(rateLabel); labelPane.add(numPeriodsLabel); labelPane.add(paymentLabel); //Layout the text fields in a panel JPanel fieldPane = new JPanel(); fieldPane.setLayout(new GridLayout(0, 1)); fieldPane.add(amountField); fieldPane.add(rateField); fieldPane.add(numPeriodsField); fieldPane.add(paymentField); //Put the panels in another panel, labels on left, //text fields on right JPanel contentPane = new JPanel(); contentPane.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); contentPane.setLayout(new BorderLayout()); contentPane.add(labelPane, BorderLayout.CENTER); contentPane.add(fieldPane, BorderLayout.EAST); setContentPane(contentPane); . . .

You may be surprised to find that the labels are laid out without reference to the text fields and, in fact, are in a different panel, yet align correctly with them. This is a side effect of the layout managers used by the program.

As the diagram illustrates, the program uses two GridLayout managers, one to lay out the column of labels and one for the column of text fields. GridLayout guarantees that all of its components are the same size, so all of the text fields are the same height and all of the labels are the same height. But the text fields are not the same height as the labels. This is achieved with a third layout manager, a BorderLayout. With just two components at East and Center, BorderLayout guarantees the columns are the same height. Now the labels and text fields are the same height, and thus, they are aligned. Another way to get labels and text fields to align is to use the AWT's most flexible, complex layout manager: GridBagLayout . Refer to the TextSamplerDemo program for an example. In particular, look at this handy method, which you can probably copy verbatim into your programs:
addLabelTextRows(JLabel[] labels, JTextField[] textFields, GridBagLayout gridbag, Container container)

Providing a Password Field


Swing provides the JPasswordField class, a subclass of JTextField, to use in place of a text field for password entry. For security reasons, a password field doesn't show the characters the user types. Instead the field displays another character such as an asterisk '*'. As another security precaution, the password field stores its value as an array of characters, rather than as a string.
PasswordDemo

brings up a small window to prompt the user to type in a password:

Here's the code from PasswordDemo that creates and sets up the password field.
JPasswordField passwordField = new JPasswordField(10); passwordField.setEchoChar('#');

passwordField.addActionListener(new ActionListener() { ... }); As with text fields, the argument passed into the JPasswordField constructor

indicates that the field should be 10 columns wide. By default a password field displays an asterisk '*' for each character typed. The call to setEchoChar changes it to a pound sign '#'. Finally, the code adds an action listener to the password field, which action-validates the value typed in by the user. Here's the implementation of the action listener's actionPerformed method:
public void actionPerformed(ActionEvent e) { JPasswordField input = (JPasswordField)e.getSource(); char[] password = input.getPassword(); if (isPasswordCorrect(password)) { JOptionPane.showMessageDialog(f, "Success! You typed the right password."); } else { JOptionPane.showMessageDialog(f, "Invalid password. Try again.", "Error Message", JOptionPane.ERROR_MESSAGE); } } The getPassword returns a character array. Password information should

not be stored or

passed around in strings because strings are not secure. A program using a password field typically validates the password before completing any actions requiring the password. This program calls a private method, isPasswordCorrect, that compares the value returned by getPassword to a value stored in a character array. Note: The getPassword method did not exist in Swing 1.0.3 and earlier releases. In those releases, you have to use getText. In that case, your program should convert the value returned from getText to a character array upon return. You should not store the value in a String. In releases that contain the getPassword method, getText has been deprecated.

The Text Field and Password Field API


The following tables list the commonly used JTextField and JPasswordField constructors and methods. Other methods you are likely to call are defined in JTextComponent. Refer to the API tables in Summary of Text. You might also invoke methods on a text field or password field that it inherits from its other ancestors, such as setPreferredSize, setForeground, setBackground, setFont, and so on. See The JComponent Class for tables of commonly used inherited methods. The API for using text fields and password fields falls into these categories:

Setting or Getting the Field's Contents Fine Tuning the Field's Appearance Implementing the Field's Functionality

Setting or Getting the Field's Contents Method or Constructor Purpose


JTextField() JTextField(String) JTextField(String, int) JTextField(int) JTextField(Document, String, int) JPasswordField() JPasswordField(String) JPasswordField(String, int) JPasswordField(int) JPasswordField(Document, String, int) void setText(String) String getText()

Create a text field. When present, the int argument specifies the desired width in columns. The String argument contains the field's initial text. The Document argument provides a custom document for the field. Create a password field. When present, the int argument specifies the desired width in columns. The String argument contains the field's initial text. The Document argument provides a custom document for the field.

Set or get the text displayed by the text field. Note that getText is deprecated for password fields in Swing 1.0.3 and higher releases. Set or get the text displayed by the text field. Note that char[] getPassword() this method does not exist in Swing 1.0.3 and lower (in JPasswordField) releases. Fine Tuning the Field's Appearance Method or Constructor Purpose void setEditable(boolean) Set or get whether the user can edit the text in the boolean isEditable() text field. Set or get the number of columns displayed by the void setColumns(int); text field. This is really just a hint for computing the int getColumns() field's preferred width. Get the width of the text field's columns. This value int getColumnWidth() is established implicitly by the font. Set or get how the text is aligned horizontally within void its area. You can use JTextField.LEFT, setHorizontalAlignment(int); int getHorizontalAlignment() JTextField.CENTER, and JTextField.RIGHT for arguments. void setEchoChar(char) Set or get the echo character -- the character char getEchoChar() displayed instead of the actual characters typed by (in JPasswordField) the user. Implementing the Field's Functionality Method or Constructor Purpose void addActionListener(ActionListener) Add or remove an action listener.

void removeActionListener(ActionListener) Document createDefaultModel()

Override this method to provide a subclass with a custom document.

Examples that Use Text Fields and Password Fields


This table shows the examples that use JTextField or JPasswordField and where those examples are described. Where Example Notes Described An applet that uses a basic text field with an TextDemo This section action listener. Uses and provides implementations for two TextFieldDemo This section different types of change-validated fields. PasswordDemo This section Uses an action-validated password field. Uses a grid bag layout to align labels with text fields. See the addParameterRow method in ControlPane , Let's Play! Utilities Utilities . Part of the BINGO player application. How to Make Includes a text field whose value is checked. Part CustomDialog.java of DialogDemo (under the More Dialogs tab). Dialogs
Trail: Creating a GUI with JFC/Swing Lesson: Writing Event Listeners

How to Write a List Selection Listener


List selection events occur when the selection in a list or table is either changing or has just changed. List selection events are fired from an object that implements the ListSelectionModel interface. To get a list or table's list selection model object, use the getSelectionModel method. To detect list selection events, you register a listener on the appropriate list selection model object. The JList class also gives you the option of registering a listener on the list itself, rather than directly on the list selection model. This section looks at an example that shows how to listen to list selection events on a selection model. Examples that Use List Selection Listeners lists examples that listen on the list directly. The selection model is shared by a list and a table. You can dynamically change the selection mode to any of the three supported modes:

single selection mode single interval selection mode multiple interval selection mode

Here's a picture of the example running:

This figure has been reduced to fit on the page. Click the image to view it at its natural size. Try this: 1. Compile and run the application. The main source file is ListSelectionDemo. See Getting Started with Swing if you need help compiling or running this application. 2. Select and deselect items in the list and table. The mouse and keyboard commands required to select items depends on the look and feel. For the Java Look & Feel, click the left mouse button to begin a selection, use the shift key to extend a selection contiguously, and use the control key to extend a selection discontiguously. Dragging the mouse moves or extends the selection, depending on the list selection mode. Here's the code from ListSelectionDemo that sets up the selection model and adds a listener to it:
...//where the member variables are defined JList list; JTable table; ...//in the init method: listSelectionModel = list.getSelectionModel(); listSelectionModel.addListSelectionListener( new SharedListSelectionHandler()); ... table.setSelectionModel(listSelectionModel);

And here's the code for the listener, which works for all the possible selection modes:
class SharedListSelectionHandler implements ListSelectionListener {

public void valueChanged(ListSelectionEvent e) { ListSelectionModel lsm = (ListSelectionModel)e.getSource(); int firstIndex = e.getFirstIndex(); int lastIndex = e.getLastIndex(); boolean isAdjusting = e.getValueIsAdjusting(); output.append("Event for indexes " + firstIndex + " - " + lastIndex + "; isAdjusting is " + isAdjusting + "; selected indexes:"); if (lsm.isSelectionEmpty()) { output.append(" <none>"); } else { // Find out which indexes are selected. int minIndex = lsm.getMinSelectionIndex(); int maxIndex = lsm.getMaxSelectionIndex(); for (int i = minIndex; i <= maxIndex; i++) { if (lsm.isSelectedIndex(i)) { output.append(" " + i); } } } output.append(newline); } }

This valueChanged method displays the first and last indices reported by the event, the value of the event's isAdjusting flag, and the indices currently selected. Note that the first and last indices reported by the event indicate the inclusive range of items for which the selection has changed. If the selection mode is multiple interval selection some items within the range might not have changed. The isAdjusting flag is true if the user is still manipulating the selection, and false if the user has finished changing the selection. The ListSelectionEvent object passed into valueChanged indicates only that the selection has changed. The event contains no information about the current selection. So, this method queries the selection model to figure out the current selection. Note: The output from this program depends on the version of Swing you are using. Swing 1.0.x contains several bugs and the operation of lists and tables were inconsistent. Later versions of Swing fix these problems.

The List Selection Event API


The ListSelectionListener interface has just one method, so it has no corresponding adapter class. Here's the method:
void valueChanged(ListSelectionEvent)

Called when the selection in the listened-to component is changing, as well as just after the selection has changed.

Each list selection event method has a single parameter: a ListSelectionEvent object. The event object tells the listener that the selection changed. One list selection event can indicate a change in selection on multiple, discontiguous items in the list. To get the source of a ListSelectionEvent, use the getSource method, which ListSelectionEvent inherits from EventObject . If you register a list selection listener on a list directly, then the source for each event is the list. Otherwise, the source is the selection model. The ListSelectionEvent class defines the following handy methods:
int getFirstIndex()

int getLastIndex()

Returns the index of the first item whose selection value has changed. Note that for multiple interval selection, the first and last items are guaranteed to have changed but items between them might not have. Returns the index of the last item whose selection value has changed. Note that for multiple interval selection, the first and last items are guaranteed to have changed but items between them might not have.

int getValueIsAdjusting() Returns true if the selection

is still changing. Many list selection listeners are interested only in the final state of the selection and can ignore list selection events when this method returns true.

Examples that Use List Selection Listeners


The following table lists the examples that use list selection listeners. Where Example Notes Described Reports all list selection events that occur on a list and on a table. The table and the list share ListSelectionDemo This section a list selection model, so only one listener is required. Let's the user dynamically change the selection mode. How to Use Listens to events on a single-selection list (not SplitPaneDemo Lists on the list's selection model). Uses two different list selection listeners on How to Use one table. One listener listens to list selection SimpleTableSelectionDemo Tables events on table columns, the other listens to list selection events on table rows.

Trail: Creating a GUI with JFC/Swing

Lesson: Getting Started with Swing

This lesson gives you a quick introduction to using the JFC Swing packages to create a program's GUI. First, it tells you what the JFC and Swing are. Next, it helps you get the necessary releases and use them to compile and run a Swing program. Then it shows you how to run applets. Finally, it takes you on a whirlwind tour of a simple Swing application. If you're more interested in learning concepts than in running programs right now, feel free to skip part or all of this lesson and to go to the next lesson, Swing Features and Concepts . Then return here when you're ready to start programming.

About the JFC and Swing


This section gives you a little history about the JFC and Swing. If you've developed programs using AWT components, you'll probably be interested in the description of the differences between AWT and Swing components.

Compiling and Running Swing Programs


To write programs using the Swing components, you must first download the appropriate JDK and JFC releases. Then you can follow this section's instructions to compile and run the small Swing application provided.

Running Swing Applets


To write Swing applets, you must first be able to run them. This section provides two applets, with instructions for running them.

A Quick Tour of a Swing Application's Code


This section takes you through the code for a small Swing application. You'll see the code that a Swing application absolutely must have, and you'll learn about some commonly used Swing features.
Trail: Creating a GUI with JFC/Swing Lesson: Using Swing Components

How to Make Frames (Main Windows)


A frame, implemented as an instance of the JFrame class, is a window that has decorations such as a border, a title, and buttons for closing and iconifying the window. Applications with a GUI typically use at least one frame. Applets sometimes use frames, as well. To make a window that's dependent on another window -- disappearing when the other window is iconified, for example -- use a dialog instead of a frame. To make a window that appears within another window, use an internal frame.

Here are two pictures of an empty-looking frame, each taken on a different platform. Solaris Windows

Note: The decorations on a frame are platform-dependent. You cannot change the decorations on a frame.

The Example Explained


The following code creates and sets up the frame from the previous figure and makes it visible onscreen. You can find the whole program in FrameDemo.java .
public static void main(String s[]) { JFrame frame = new JFrame("FrameDemo");

frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); //...create a blank label, set its preferred size... frame.getContentPane().add(emptyLabel, BorderLayout.CENTER); frame.pack(); frame.setVisible(true); }

The first line of code creates a frame with the constructor that lets you set the frame's title. The only other constructor provided by JFrame is a no-argument constructor. Next the code adds a window listener to the frame. The listener's implementation makes the program exit when the user closes the frame. This behavior is appropriate for this program because the program has only one frame, and closing the frame makes the program useless. If the program didn't exit, then it would continue to run but have no visible GUI and no way of making any GUI visible. See Responding to Window-Closing Events for more information. The bold line in the code segment adds a blank label to the frame's content pane. If you're not already familiar with content panes and how to add components to them, please read Adding Components to the Content Pane. The next line gives the frame a size, using the pack method. The pack method sizes the frame so that all its contents are at or above their preferred sizes. An alternative to pack is

to establish a frame's size explicitly by calling setSize. In general, using pack is preferable to calling setSize, since pack leaves the frame's layout manager in charge of the frame's size, and layout managers are good at adjusting to platform dependencies and other factors that affect component size. The last line uses the setVisible method to make the frame appear onscreen. Sometimes you might see the show method used instead of setVisible(true). The two usages are equivalent, but we use setVisible(true) for consistency's sake. Note: If any part of the frame has been realized you should invoke setVisible from the event dispatching thread. For a definition of the term "realized" and information about the event dispatching thread, refer to Threads and Swing .

Responding to Window-Closing Events


By default, when the user closes a frame onscreen, the frame is hidden. Although invisible, the frame still exists and the program can make it visible again. If you want different behavior, then you need to either register a window listener that handles window-closing events, or you need to specify default close behavior using the setDefaultCloseOperation method. You can even do both. The argument to setDefaultCloseOperation must be one of the following values, which are defined in the WindowConstants interface (which JFrame implements):

-- Don't do anything when the user's requests that the frame close. Instead, the program should probably use a window listener that performs some other action in its windowClosing method. HIDE_ON_CLOSE (the default) -- Hide the frame when the user closes it. This removes the frame from the screen. DISPOSE_ON_CLOSE -- Hide and dispose of the frame when the user closes it. This removes the frame from the screen and frees up any resources used by it.
DO_NOTHING_ON_CLOSE

The default close operation is executed after the frame's window listeners (if any) handle the window-closing event. So, for example, assume that you specify that the default close operation is to dispose of the frame. You also implement a window listener that tests whether the frame is the last one and, if so, exits the application. Under these conditions, when the user closes a frame, the window listener will be called first. If it doesn't exit the application, then the default close operation -- disposing of the frame -- will then be performed. For more information about handling window-closing events, see How to Write a Window Listener . Besides handling window-closing events, window listeners can also react to other window state changes, such as iconification and activation.

The Frame API

The following tables list the commonly used JFrame constructors and methods. Other methods you're likely to call are defined by the java.awt.Frame and java.awt.Window classes, from which JFrame descends. These methods include pack, setSize, setVisible, setTitle, and getTitle. Because each JFrame object has a root pane, frames have support for interposing input and painting behavior in front of the frame's children, placing children on different "layers", and for Swing menu bars. These topics are introduced in Using Top-Level Containers. and explained in detail in How to Use Root Panes. The API for using frames falls into these categories:

Creating and Setting Up a Frame Methods Related to the Root Pane Creating and Setting Up a Frame Purpose Create a frame that is initially invisible. Call setVisible(true) on the frame to make it visible. The String argument provides a title for the frame. You can also use setTitle to set a frame's title. Set or get the operation that occurs when the user pushes the close button on this frame. Possible choices are:

Method
JFrame() JFrame(String)

void setDefaultCloseOperation(int) int getDefaultCloseOperation()

DO_NOTHING_ON_CLOSE HIDE_ON_CLOSE (the default) DISPOSE_ON_CLOSE

These constants are defined in the WindowConstants interface, which JFrame implements. Methods Related to the Root Pane Method Purpose void setContentPane(Container) Set or get the frame's content pane. The content pane contains the frame's visible GUI components and Container getContentPane() should be opaque. Create, set, or get the frame's root pane. The root JRootPane createRootPane() void setRootPane(JRootPane) pane manages the interior of the frame including the JRootPane getRootPane() content pane, the glass pane, and so on. void setJMenuBar(JMenuBar) Set or get the frame's menu bar to manage a set of JMenuBar getJMenuBar() menus for the frame. void setGlassPane(Component) Set or get the frame's glass pane. You can use the

glass pane to intercept mouse events. Set or get the frame's layered pane. You can use the void setLayeredPane(JLayeredPane) frame's layered pane to put components on top of or JLayeredPane getLayeredPane() behind other components.
Component getGlassPane()

Examples that Use Frames


All of the examples in this trail that are standalone applications use JFrame. The following table lists a few and tells you where each is discussed. Where Example Notes Described The Example FrameDemo Displays a basic frame with one component. Explained A study in creating and destroying windows, in Framework -implementing a menu bar, and in exiting an application. A subclass of JFrame that adds components to the How to Use ColorChooserDemo Color Choosers default content pane. A subclass of JFrame that sets the frame's content How to Use TableDemo Tables pane. How to Use Illustrates how to use a layered pane (but not the LayeredPaneDemo Layered Panes frame's layered pane). GlassPaneDemo The Glass Pane Illustrates the use of a frame's glass pane. How to Use MenuDemo Shows how to put a JMenuBar in a JFrame. Menus

Trail: Creating a GUI with JFC/Swing Lesson: Using Swing Components

How to Use Internal Frames


With the JInternalFrame class, you can display a JFrame-like window within another window. Usually, you add internal frames to a desktop pane. The desktop pane, in turn, might be used as the content pane of a JFrame. The desktop pane is an instance of JDesktopPane , which is a subclass of JLayeredPane that has added API for managing multiple overlapping internal frames. You should consider carefully whether to base your program's GUI around frames or internal frames. Switching from internal frames to frames or vice versa isn't necessarily a simple task. By experimenting with both frames and internal frames, you can get an idea of the tradeoffs involved in choosing one over the other.

Here is a picture of an application that has two internal frames (one of which is iconified) inside a regular frame:

As the figure shows, the window decorations on an internal frame reflect the Java Look & Feel. However, the window that contains the internal frame has the decorations for the native look and feel (in this case, Motif). Try this: 1. Compile and run the application. The source files are InternalFrameDemo.java and MyInternalFrame.java . See Getting Started with Swing if you need help compiling or running this application. 2. Create new internal frames using the Create item in the Document menu. Each internal frame comes up 30 pixels lower and to the right of the place where the previous internal frame first appeared. This functionality is implemented in the MyInternalFrame class, which is the custom subclass of JInternalFrame.

The following code, taken from InternalFrameDemo.java , creates the desktop and internal frames in the previous example.
...//In the constructor of InternalFrameDemo, a JFrame subclass: desktop = new JDesktopPane(); createFrame(); //Create first window setContentPane(desktop); ... //Make dragging faster: desktop.putClientProperty("JDesktopPane.dragMode", "outline"); ... protected void createFrame() { MyInternalFrame frame = new MyInternalFrame(); frame.setVisible(true); //necessary as of kestrel desktop.add(frame); try { frame.setSelected(true); } catch (java.beans.PropertyVetoException e) {} } ...//In the constructor of MyInternalFrame, a JInternalFrame subclass:

static int openFrameCount = 0; static final int xOffset = 30, yOffset = 30; public MyInternalFrame() { super("Document #" + (++openFrameCount), true, //resizable true, //closable true, //maximizable true);//iconifiable //...Create the GUI and put it in the window... //...Then set the window size or call pack... ... //Set the window's location. setLocation(xOffset*openFrameCount, yOffset*openFrameCount); }

Internal Frames vs. Regular Frames


The code for using internal frames is similar in many ways to the code for using regular Swing frames. Because internal frames have root panes, setting up the GUI for a JInternalFrame is very similar to setting up the GUI for a JFrame. JInternalFrame also provides other API, such as pack, that makes it similar to JFrame. Note: Just as for a regular frame, you must invoke setVisible(true) or show() on an internal frame to display it. In early versions of the Java 2 platform (such as v1.2.2), this code has no effect because the internal frame is visible by default. However, starting in the Kestrel release, the internal frame does not appear until you explicitly make it visible. Internal frames aren't windows or top-level containers, however, which makes them different from frames. For example, you must add an internal frame to a container (usually a JDesktopPane); an internal frame can't be the root of a containment hierarchy. Also, internal frames don't generate window events. Instead, the user actions that would cause a frame to fire window events cause an internal frame to fire internal frame events. Because internal frames are implemented with platform-independent code, they add some features that frames can't give you. One such feature is that internal frames give you more control over their state and capabilities than frames do. You can programatically iconify or maximize an internal frame. You can also specify what icon goes in the internal frame's title bar. You can even specify whether the internal frame has the window decorations to support resizing, iconifying, closing, and maximizing. Another feature is that internal frames are designed to work within desktop panes. The JInternalFrame API contains methods such as moveToFront that work only if the internal frame's container is a layered pane such as a JDesktopPane.

Rules of Using Internal Frames


If you've built any programs using JFrame and the other Swing components, then you already know a lot about how to use internal frames. The following list summarizes the

rules for using internal frames. For additional information, see How to Make Frames and The JComponent Class. You must set the size of the internal frame. If you don't set the size of the internal frame, it will have zero size and thus never be visible. You can set the size using one of the following methods: setSize, pack, or setBounds. As a rule, you should set the location of the internal frame. If you don't set the location of the internal frame, it will come up at 0,0 (the upper left of its container). You can use the setLocation or setBounds method to specify the upper left point of the internal frame, relative to its container. To add components to an internal frame, you add them to the internal frame's content pane. This is exactly like the JFrame situation. See Adding Components to the Content Pane for details. Dialogs that are internal frames should be implemented using JOptionPane or JInternalFrame, not JDialog. To create a simple dialog, you can use the JOptionPane showInternalXxxDialog methods, as described in How to Make Dialogs. You must add an internal frame to a container. If you don't add the internal frame to a container (usually a JDesktopPane), the internal frame won't appear. You need to call show or setVisible on internal frames. Beginning with the Kestrel release, internal frames are invisible by default. You must invoke setVisible(true) or show() to make them visible. Internal frames fire internal frame events, not window events. Handling internal frame events is almost identical to handling window events. See How to Write an Internal Frame Listener for more information. Performance Tip: Because dragging internal frames can be slow, Swing 1.1.1 adds a way to make it zippy: outline dragging. With outline dragging, only the outline of the internal frame is painted at the current mouse position while the window's being dragged. The internal frame's innards are not repainted at a new position until dragging stops. The default, slower behavior is to reposition and repaint the entire internal frame continuously while it's being moved. In a future release, the Swing team plans to add a method to let you specify outline dragging. Until that method is added, you can specify outline dragging by setting a client property of the desktop pane, like this:
desktop.putClientProperty("JDesktopPane.dragMode", "outline");

The preceding code has no effect in JFC implementations before Swing 1.1.1 Beta 1.

The Internal Frame API


The following tables list the commonly used JInternalFrame constructors and methods, as well as a few methods that JDesktopPane provides. Besides the API listed in this

section, JInternalFrame inherits useful API from its superclasses, JComponent, Component, and Container. See The JComponent Class for lists of methods from those classes. Like JInternalFrame, JDesktopPane descends from JComponent, and thus provides the methods described in The JComponent Class. Because JDesktopPane extends JLayeredPane, it also supports the methods described in The Layered Pane API. The API for using internal frames falls into these categories:

Creating the internal frame Adding components to the internal frame Specifying the internal frame's visibility, size, and location Performing window operations on the internal frame Controlling window decorations and capabilities Using the JDesktopPane API

Creating the Internal Frame Constructor or Method Purpose Create a JInternalFrame instance. The first JInternalFrame() argument specifies the title (if any) to be JInternalFrame(String) displayed by the internal frame. The rest of the JInternalFrame(String, boolean) arguments specify whether the internal frame JInternalFrame(String, boolean, boolean) should contain decorations allowing the user to JInternalFrame(String, boolean, resize, close, maximize, and iconify the internal boolean, boolean) frame (specified in that order). The default JInternalFrame(String, boolean, value for each boolean argument is false, boolean, boolean, boolean) which means that the operation is not allowed.
JOptionPane class methods: showInternalConfirmDialog showInternalInputDialog showInternalMessageDialog showInternalOptionDialog

Create a JInternalFrame that simulates a dialog. See How to Make Dialogs for details.

Adding Components to the Internal Frame Method Purpose Set or get the internal frame's content pane, which void setContentPane(Container) generally contains all of the internal frame's GUI, with Container getContentPane() the exception of the menu bar and window decorations. void setJMenuBar(JMenuBar) Set or get the internal frame's menu bar. Note that some JMenuBar getJMenuBar() early Swing releases do not include this method. Specifying the Internal Frame's Visibility, Size, and Location Purpose

Method Make the internal frame visible (if true) or invisible (if false). You should invoke setVisible(true) on each JInternalFrame before adding it to its container. (Inherited from Component). Size the internal frame so that its components are at their preferred sizes. Set the position of the internal frame. (Inherited from Component). Explicitly set the size and location of the internal frame. (Inherited from Component).

void setVisible(boolean)

void pack() void setLocation(Point) void setLocation(int, int) void setBounds(Rectangle) void setBounds(int, int, int, int)

void setSize(Dimension) void setSize(int, int)

Explicitly set the size of the internal frame. (Inherited from Component). Performing Window Operations on the Internal Frame Method Purpose Set or get what the internal frame does when the user attempts to "close" the internal frame. The void default value is HIDE_ON_CLOSE. Other possible setDefaultCloseOperation(int) int getDefaultCloseOperation() values are DO_NOTHING_ON_CLOSE and DISPOSE_ON_CLOSE. See Responding to WindowClosing Events for details.
void addInternalFrameListener( InternalFrameListener) void removeInternalFrameListener( InternalFrameListener) void moveToFront() void moveToBack() void setClosed(boolean) boolean isClosed() void setIcon(boolean) boolean isIcon() void setMaximum(boolean) boolean isMaximum() void setSelected(boolean) boolean isSelected()

Add or remove an internal frame listener (JInternalFrame's equivalent of a window listener). See How to Write an Internal Frame Listener for more information. If the internal frame's parent is a layered pane such as a desktop pane, moves the internal frame to the front or back (respectively) of its layer. Set or get whether the internal frame is currently closed. Iconify or deiconify the internal frame, or determine whether it's currently iconified. Maximize or restore the internal frame, or determine whether it's maximized. Set or get whether the internal frame is the currently

"selected" (activated) internal frame. Controlling Window Decorations and Capabilities Method Purpose void setFrameIcon(Icon) Set or get the icon displayed in the title bar of the internal Icon getFrameIcon() frame (usually in the top-left corner).
void setClosable(boolean) boolean isClosable() void setIconifiable(boolean) boolean isIconifiable() void setMaximizable(boolean) boolean isMaximizable() void setResizable(boolean) boolean isResizable() void setTitle(String) String getTitle()

Set or get whether the user can close the internal frame. Set or get whether the internal frame can be iconified. Set or get whether the user can maximize this internal frame. Set or get whether the internal frame can be resized. Set or get the window title.

Using the JDesktopPane API Constructor or Method


JDesktopPane() JInternalFrame[] getAllFrames() JInternalFrame[] getAllFramesInLayer(int)

Purpose Creates a new instance of JDesktopPane. Returns all JInternalFrame objects that the desktop contains. Returns all JInternalFrame objects that the desktop contains that are in the specified layer. See How to Use Layered Panes for information about layers.

Examples that Use Internal Frames


The following examples use internal frames. Because internal frames are similar to regular frames, you should also look at Examples that Use Frames. Where Example Notes Described Implements an internal frame that appears MyInternalFrame This page. at an offset to the previously created internal frame. Lets you create internal frames (instances InternalFrameDemo of MyInternalFrame) that go into the This page. application's JDesktopPane. How to Write an Demonstrates listening for internal frame InternalFrameEventDemo Internal Frame events. Also demonstrates positioning Listener internal frames within a desktop pane.

Trail: Creating a GUI with JFC/Swing Lesson: Using Swing Components

How to Make Frames (Main Windows)


A frame, implemented as an instance of the JFrame class, is a window that has decorations such as a border, a title, and buttons for closing and iconifying the window. Applications with a GUI typically use at least one frame. Applets sometimes use frames, as well. To make a window that's dependent on another window -- disappearing when the other window is iconified, for example -- use a dialog instead of a frame. To make a window that appears within another window, use an internal frame. Here are two pictures of an empty-looking frame, each taken on a different platform. Solaris Windows

Note: The decorations on a frame are platform-dependent. You cannot change the decorations on a frame.

The Example Explained


The following code creates and sets up the frame from the previous figure and makes it visible onscreen. You can find the whole program in FrameDemo.java .
public static void main(String s[]) { JFrame frame = new JFrame("FrameDemo");

frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); //...create a blank label, set its preferred size... frame.getContentPane().add(emptyLabel, BorderLayout.CENTER); frame.pack(); frame.setVisible(true); }

The first line of code creates a frame with the constructor that lets you set the frame's title. The only other constructor provided by JFrame is a no-argument constructor.

Next the code adds a window listener to the frame. The listener's implementation makes the program exit when the user closes the frame. This behavior is appropriate for this program because the program has only one frame, and closing the frame makes the program useless. If the program didn't exit, then it would continue to run but have no visible GUI and no way of making any GUI visible. See Responding to Window-Closing Events for more information. The bold line in the code segment adds a blank label to the frame's content pane. If you're not already familiar with content panes and how to add components to them, please read Adding Components to the Content Pane. The next line gives the frame a size, using the pack method. The pack method sizes the frame so that all its contents are at or above their preferred sizes. An alternative to pack is to establish a frame's size explicitly by calling setSize. In general, using pack is preferable to calling setSize, since pack leaves the frame's layout manager in charge of the frame's size, and layout managers are good at adjusting to platform dependencies and other factors that affect component size. The last line uses the setVisible method to make the frame appear onscreen. Sometimes you might see the show method used instead of setVisible(true). The two usages are equivalent, but we use setVisible(true) for consistency's sake. Note: If any part of the frame has been realized you should invoke setVisible from the event dispatching thread. For a definition of the term "realized" and information about the event dispatching thread, refer to Threads and Swing .

Responding to Window-Closing Events


By default, when the user closes a frame onscreen, the frame is hidden. Although invisible, the frame still exists and the program can make it visible again. If you want different behavior, then you need to either register a window listener that handles window-closing events, or you need to specify default close behavior using the setDefaultCloseOperation method. You can even do both. The argument to setDefaultCloseOperation must be one of the following values, which are defined in the WindowConstants interface (which JFrame implements):

-- Don't do anything when the user's requests that the frame close. Instead, the program should probably use a window listener that performs some other action in its windowClosing method. HIDE_ON_CLOSE (the default) -- Hide the frame when the user closes it. This removes the frame from the screen. DISPOSE_ON_CLOSE -- Hide and dispose of the frame when the user closes it. This removes the frame from the screen and frees up any resources used by it.
DO_NOTHING_ON_CLOSE

The default close operation is executed after the frame's window listeners (if any) handle the window-closing event. So, for example, assume that you specify that the default close operation is to dispose of the frame. You also implement a window listener that tests whether the frame is the last one and, if so, exits the application. Under these conditions, when the user closes a frame, the window listener will be called first. If it doesn't exit the application, then the default close operation -- disposing of the frame -- will then be performed. For more information about handling window-closing events, see How to Write a Window Listener . Besides handling window-closing events, window listeners can also react to other window state changes, such as iconification and activation.

The Frame API


The following tables list the commonly used JFrame constructors and methods. Other methods you're likely to call are defined by the java.awt.Frame and java.awt.Window classes, from which JFrame descends. These methods include pack, setSize, setVisible, setTitle, and getTitle. Because each JFrame object has a root pane, frames have support for interposing input and painting behavior in front of the frame's children, placing children on different "layers", and for Swing menu bars. These topics are introduced in Using Top-Level Containers. and explained in detail in How to Use Root Panes. The API for using frames falls into these categories:

Creating and Setting Up a Frame Methods Related to the Root Pane Creating and Setting Up a Frame Purpose Create a frame that is initially invisible. Call setVisible(true) on the frame to make it visible. The String argument provides a title for the frame. You can also use setTitle to set a frame's title. Set or get the operation that occurs when the user pushes the close button on this frame. Possible choices are:
DO_NOTHING_ON_CLOSE HIDE_ON_CLOSE (the default) DISPOSE_ON_CLOSE

Method
JFrame() JFrame(String)

void setDefaultCloseOperation(int) int getDefaultCloseOperation()

These constants are defined in the WindowConstants interface, which JFrame

implements. Methods Related to the Root Pane Method Purpose void setContentPane(Container) Set or get the frame's content pane. The content pane contains the frame's visible GUI components and Container getContentPane() should be opaque. Create, set, or get the frame's root pane. The root JRootPane createRootPane() void setRootPane(JRootPane) pane manages the interior of the frame including the JRootPane getRootPane() content pane, the glass pane, and so on. void setJMenuBar(JMenuBar) Set or get the frame's menu bar to manage a set of JMenuBar getJMenuBar() menus for the frame. void setGlassPane(Component) Set or get the frame's glass pane. You can use the Component getGlassPane() glass pane to intercept mouse events. Set or get the frame's layered pane. You can use the void setLayeredPane(JLayeredPane) frame's layered pane to put components on top of or JLayeredPane getLayeredPane() behind other components.

Examples that Use Frames


All of the examples in this trail that are standalone applications use JFrame. The following table lists a few and tells you where each is discussed. Where Example Notes Described The Example FrameDemo Displays a basic frame with one component. Explained A study in creating and destroying windows, in Framework -implementing a menu bar, and in exiting an application. A subclass of JFrame that adds components to the How to Use ColorChooserDemo Color Choosers default content pane. A subclass of JFrame that sets the frame's content How to Use TableDemo Tables pane. How to Use Illustrates how to use a layered pane (but not the LayeredPaneDemo Layered Panes frame's layered pane). GlassPaneDemo The Glass Pane Illustrates the use of a frame's glass pane. How to Use MenuDemo Shows how to put a JMenuBar in a JFrame. Menus
Trail: Creating a GUI with JFC/Swing Lesson: Using Swing Components

Using Top-Level Containers

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:

Swing provides three generally useful top-level container classes: 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 AWT Window 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.

To appear onscreen, every GUI component must be part of a containment hierarchy. Each containment hierarchy has a top-level container as its root. Each top-level container has a content pane that, generally speaking, contains the visible components in that top-level container's GUI. You can optionally add a menu bar to a top-level container. The menu bar is positioned within the top-level container, but outside the content pane.

Here's a picture of a frame created by an application. The frame contains an empty cyan menu bar and, in the frame's content pane, a large yellow label.

You can find the entire source for this example in TopLevelDemo.java . Although the example uses a JFrame in a standalone application, the same concepts apply to JApplets and JDialogs. 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:

Top-Level Containers and Containment Hierarchies Adding Components to the Content Pane Adding a Menu Bar The Root Pane (a.k.a. The Missing Details)

Top-Level Containers and Containment Hierarchies


Each program that uses Swing components has at least one top-level container. This toplevel 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.

Adding Components to the Content Pane


Here's the code that the preceding example uses to get a frame's content pane and add the yellow label to it:
frame.getContentPane().add(yellowLabel, BorderLayout.CENTER);

As the code shows, you find the content pane of a top-level container by calling the 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

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.
Container

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 as JScrollPane, JSplitPane, and JTabbedPane as content panes. A non-opaque content pane results in messy repaints. Although you can make any Swing component opaque by invoking setOpaque(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.

Adding a Menu Bar


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:
frame.setJMenuBar(cyanMenuBar);

For more information about implementing menus and menu bars, see How to Use Menus.

The Root Pane


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):

We've already told you about the content pane and the optional menu bar. The two other components that a root pane adds are a layered pane and a glass pane. The layered pane directly contains the menu bar and content pane, and enables Z-ordering of other components you might add. The glass pane is often used to intercept input events occuring over the top-level container, and can also be used to paint over multiple components. For more information about the intricacies of root panes, see How to Use Root Panes.
Trail: Creating a GUI with JFC/Swing Lesson: Using Swing Components

How to Use Root Panes


In general, you don't directly create a JRootPane object. Instead, you get a JRootPane (whether you want it or not!) when you instantiate JInternalFrame or one of the toplevel Swing containers, such as JApplet, JDialog, and JFrame. Using Top-Level Containers tells you the basics of using root panes -- getting the content pane, setting its layout manager, and adding Swing components to it. This section tells you more about root panes, including the components that make up a root pane and how you can use them. Another place to get information about root panes is The Swing Connection, especially the article Understanding Containers.

As the preceding figure shows, a root pane has four parts: The glass pane Hidden, by default. If you make the glass pane visible, then it's like a sheet of glass over all the other parts of the root pane. It's completely transparent unless you implement the glass pane's paint method so that it does something, and it intercepts input events for the root pane. In the next section, you'll see an example of using a glass pane. The layered pane

Serves to position its contents, which consist of the content pane and the optional menu bar. Can also hold other components in a specified Z order. For information, see The Layered Pane. The content pane The container of the root pane's visible components, excluding the menu bar. For information on using the content pane, see Using Top-Level Containers. The optional menu bar The home for the root pane's container's menus. If the container has a menu bar, you generally use the container's setJMenuBar method to put the menu bar in the appropriate place. For more information on using menus and menu bars, see How to Use Menus.

The Glass Pane


The glass pane is useful when you want to be able to catch events or paint over an area that already contains one or more components. For example, you can deactivate mouse events for a multi-component region by having the glass pane intercept the events. Or you can display an image over multiple components using the glass pane. Here's a picture of an application that demonstrates glass pane features. It contains a check box that lets you set whether the glass pane is "visible" -- whether it can get events and paint itself onscreen. When the glass pane is visible, it blocks all input events from reaching the components in the content pane. It also paints a red dot in the place where it last detected a mouse-pressed event.

Try this: 1. Compile and run the application. The source file is GlassPaneDemo.java . See Getting Started with Swing if you need help compiling or running this application. 2. Click Button 1. The button's appearance changes to show that it's been clicked. 3. Click the check box so that the glass pane becomes "visible," and then click Button 1 again. The button does not detect the mouse-pressed event because the glass pane intercepts it. When the glass pane detects the event, it beeps and paints a red circle where you clicked. 4. Click the check box again so that the glass pane is hidden. When the root pane detects an event over the check box, it forwards it to the check box. Otherwise, the check box would not respond to clicks.

The following code from GlassPaneDemo.java shows and hides the glass pane. This program happens to create its own glass pane, setting it using the JFrame setGlassPane method. However, if a glass pane doesn't do any painting, the program might simply attach listeners to the default glass pane, as returned by getGlassPane.
...//where GlassPaneDemo's UI is initialized: JCheckBox changeButton = new JCheckBox("Glass pane \"visible\""); changeButton.setSelected(false); changeButton.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { myGlassPane.setVisible(e.getStateChange() == ItemEvent.SELECTED); } });

The next code snippet implements the mouse-event handling for the glass pane. If a mouse event occurs over the check box or menu bar, then the glass pane redispatches the event so that the check box or menu component receives it. So that the check box and menu behave properly, they also receive all drag events that started with a press in the button or menu bar.
...//In the implementation of the glass pane's mouse listener: public void mouseMoved(MouseEvent e) { redispatchMouseEvent(e, false); } .../* The mouseDragged, mouseClicked, mouseEntered, * mouseExited, and mousePressed methods have the same * implementation as mouseMoved*/... public void mouseReleased(MouseEvent e) { redispatchMouseEvent(e, true); inDrag = false; } private void redispatchMouseEvent(MouseEvent e, boolean repaint) { boolean inButton = false; boolean inMenuBar = false; Point glassPanePoint = e.getPoint(); Component component = null; Container container = contentPane; Point containerPoint = SwingUtilities.convertPoint( glassPane, glassPanePoint, contentPane); int eventID = e.getID(); if (containerPoint.y < 0) { inMenuBar = true; //...set container and containerPoint accordingly... testForDrag(eventID); }

component = SwingUtilities.getDeepestComponentAt( container, containerPoint.x, containerPoint.y); if (component.equals(liveButton)) { inButton = true; testForDrag(eventID); } if (inMenuBar || inButton || inDrag) { ...//Redispatch the event to component... } if (repaint) { toolkit.beep(); glassPane.setPoint(glassPanePoint); glassPane.repaint(); }

private void testForDrag(int eventID) { if (eventID == MouseEvent.MOUSE_PRESSED) { inDrag = true; } }

Here is the code that implements the painting for the glass pane:
...//where GlassPaneDemo's UI is initialized: myGlassPane = new MyGlassPane(...); frame.setGlassPane(myGlassPane); ... /** * We have to provide our own glass pane so that it can paint. */ class MyGlassPane extends JComponent { Point point = null; public void paint(Graphics g) { if (point != null) { g.setColor(Color.red); g.fillOval(point.x - 10, point.y - 10, 20, 20); } } ...

The Layered Pane


A root pane places its menu bar and content pane in an instance of JLayeredPane--a container with depth--such that overlapping components can appear one on top of the other. This is useful for displaying popup menus above other components, for example. Your programs can also put components in the root pane's layered pane. If you do, then you should be aware that certain depths are defined to be used for specific functions, and

you should use the depths as intended. Otherwise, your components might not play well with the others. Here's a diagram that shows the functional layers and their relationship:

The table below describes the intended use for each layer and the named constant defined in the JLayeredPane class that corresponds to it: Layer Name Value Description This layer is used to position the frame's content pane and menu bar. Most programs won't use this. The root pane adds the menu bar and content pane to its layered pane at this depth.

FRAME_CONTENT_LAYER

new Integer(30000)

DEFAULT_LAYER new Integer(0)

Most components go in this layer. If you don't specify a component's depth, the layered pane puts it at this depth. This layer is useful for floating toolbars and palettes. Modal internalframe dialogs would belong in this layer. Popups go in this layer because they need to appear above just about everything. Move a component to this layer when

PALETTE_LAYER new Integer(100)

MODAL_LAYER

new Integer(200)

POPUP_LAYER

new Integer(300)

DRAG_LAYER

new Integer(400)

dragging. Return the component to its regular layer when dropped. This tutorial does not provide an example of using the root pane's layered pane. However, by modifying a few lines of code in the example described in How to Use Layered Panes, you can make the program use the root pane's layered pane instead of creating one. The left column in this table shows the code as it appears in LayeredPaneDemo.java . The right column shows how to change it: From... To...
layeredPane = new JLayeredPane(); layeredPane = getLayeredPane(); final int YFUDGE = 57; contentPane.add(layeredPane); frame.pack(); final int YFUDGE = 27; //contentPane.add(layeredPane); frame.setSize(new Dimension(350, 400)); Point origin = new Point(10, 20); Point origin = new Point(10, 70);

Because the program now uses the root pane's layered pane, the Duke label can be dragged all around inside the window and over the components in the control panel. What do you suppose happens when you bring up the combo box? Will Duke be under the combo box's menu or over it?

Notice that the layered pane's mouse listener is not notified of events when the mouse is over the combo box or the checkbox.

The Root Pane API


The tables that follow list the API for using root panes, glass panes, and content panes. For more information on using content panes, go to Using Top-Level Containers. Here are the tables in this section:

Using a Root Pane Setting or Getting the Glass Pane Setting or Getting the Content Pane

The API for using other parts of the root pane is described elsewhere:

The Layered Pane API The Menu API Using a Root Pane Purpose Get the root pane of the applet, dialog, frame, internal frame, or window. If the component contains a root pane, returns that root pane. Otherwise, returns the root pane (if any) that contains the component. Invokes the SwingUtilities getRootPane method on the JComponent.

Method
JRootPane getRootPane() (in JApplet, JDialog, JFrame, JInternalFrame, and JWindow)

JRootPane SwingUtilities.getRootPane(Component)

JRootPane getRootPane() (in JComponent)

Set or get which button (if any) is the default button in the root pane. A lookvoid setDefaultButton(JButton) and-feel-specific action, such as pressing JButton getDefaultButton() Enter, causes the button's action to be performed. Setting or Getting the Glass Pane Method Purpose
setGlassPane(Component) Component getGlassPane() (in JApplet, JDialog, JFrame, JInternalFrame, JRootPane, and JWindow)

Sets or gets the glass pane.

Setting or Getting the Content Pane Method Purpose

setContentPane(Container) Container getContentPane() (in JApplet, JDialog, JFrame, JInternalFrame, JRootPane, and JWindow)

Set or get the content pane.

Examples that Use Root Panes


Every Swing program has a root pane, but few reference it directly. The examples in the following list illustrate how to use features of JRootPane or the glass pane. Also see these lists:

Examples that Use Layered Panes Examples that Use Menus Examples that Use Frames (for examples of using content panes) Notes Uses a glass pane. Redispatches events. Sets the default button for a top-level container, using the root pane's setDefaultButton method. Sets a property on the root pane, to try to avoid a security check that can cause disturbing messages in the console in JDK 1.1.

Where Described GlassPaneDemo This section How to Use ListDialog BoxLayout Example
AppletDemo

How to Make Applets

Trail: Creating a GUI with JFC/Swing Lesson: Swing Features and Concepts

Threads and Swing


If your program creates and refers to its GUI the right way, you might not need to worry about threads. For example, if your program is an applet, it's safe to construct its GUI in the init method. And if your program is an application with the following common pattern, you're also safe:
//Thread-safe example public class MyApplication { public static void main(String[] args) { JFrame f = new JFrame(...); ...//Add components to the frame here... f.pack(); f.setVisible(true); //Don't do any more GUI work here. } ...

//All manipulation of the GUI -- setText, getText, etc. -//is performed in event handlers such as actionPerformed(). ...

However, if your program creates threads to perform tasks that affect the GUI, or if it manipulates the already-visible GUI in response to anything but a standard event, then read on! If you aren't familiar with threads, you might first want to read Doing Two or More Tasks At Once: Threads -- just for concepts. Don't bother with the details of coding threads, since we give you information about that in How to Use Threads . The Single-Thread Rule Swing components can be accessed by only one thread at a time, generally, the event-dispatching thread. Exceptions to the Rule A few operations are guaranteed to be thread safe. How to Execute Code in the Event-Dispatching Thread If you need access to the UI from outside event-handling or painting code, you can use the SwingUtilities invokeLater or invokeAndWait method.

The Single-Thread Rule


The single-thread rule is as follows: Rule: Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread. This rule might sound scary, but for many simple programs, you don't have to worry about threads. Before we go into detail about how to write Swing code, let's define the term realized. Realized means that the component has been painted on-screen, or that it is ready to be painted. A Swing component that's a top-level window is realized by having one of these methods invoked on it: setVisible(true), show, or pack. Once a window is realized, all the components that it contains are realized. Another way to realize a component is to add it to a container that's already realized. You'll see examples of realizing components later. Note: The show method does the same thing as setVisible(true).

Exceptions to the Rule


There are a few exceptions to the rule that all code that might affect a realized Swing component must run in the event-dispatching thread. A few methods are thread safe. In the Swing API documentation, thread-safe methods are marked with this text: This method is thread safe, although most Swing methods are not. An application's GUI can often be constructed and shown in the main thread.

As long as no components (Swing or otherwise) have been realized in the current runtime environment, it's fine to construct and show a GUI in the main thread of an application. To help you see why, here's an analysis of the thread safety of the thread-safe example. To refresh your memory, here are the important lines from the example:
public static void main(String[] args) { JFrame f = new JFrame(...); ...//Add components to the frame here... f.pack(); f.setVisible(true); //Don't do any more GUI work here. }

1. The example constructs the GUI in the main thread. In general, you can construct (but not show) a GUI in any thread, as long as you don't make any calls that refer to or affect already-realized components. 2. The components in the GUI are realized by the pack call. 3. Immediately afterward, the components in the GUI are shown with the setVisible (or show) call. Technically, the setVisible call is unsafe because the components have already been realized by the pack call. However, because the program doesn't already have a visible GUI, it's exceedingly unlikely that a paint request will occur before setVisible returns. 4. The main thread executes no GUI code after the setVisible call. This means that all GUI work moves from the main thread to the eventdispatching thread, and the example is, in practice, thread safe. An applet's GUI can be constructed and shown in the init method. Existing browsers don't paint an applet until after its init and start methods have been called. Thus, constructing the GUI in the applet's init method is safe, as long as you never call show() or setVisible(true) on the actual applet object. Two JComponent methods are safe to call from any thread: repaint and revalidate. These methods queue requests to be executed on the event-dispatching thread. Listener lists can be modified from any thread. It's always safe to call the addListenerTypeListener and removeListenerTypeListener methods. The add/remove operations have no effect on an event dispatch that's under way.

How to Execute Code in the Event-Dispatching Thread


Most post-initialization GUI work naturally occurs in the event-dispatching thread. Once the GUI is visible, most programs are driven by events such as button actions or mouse clicks, which are always handled in the event-dispatching thread.

However, some programs need to perform non-event-driven GUI work after the GUI is visible. Here are two examples: Programs that must perform a lengthy initialization operation before they can be used This kind of program should generally show some GUI while the initialization is occurring, and then update or change the GUI. The initialization should not occur in the event-dispatching thread; otherwise, repainting and event dispatch would stop. However, after initialization the GUI update/change should occur in the event-dispatching thread, for thread-safety reasons. Programs whose GUI must be updated as the result of nonstandard events For example, suppose a server program can get requests from other programs that might be running on different machines. These requests can come at any time, and they result in one of the server's methods being invoked in some possibly unknown thread. How can that method update the GUI? By executing the GUIupdate code in the event-dispatching thread. The SwingUtilities class provides two methods to help you run code in the eventdispatching thread:
invokeLater

Requests that some code be executed in the event-dispatching thread. This method returns immediately, without waiting for the code to execute.
invokeAndWait

Acts like invokeLater, except that this method waits for the code to execute. As a rule, you should use invokeLater rather than this method. For information on using invokeLater and invokeAndWait, and for other tips on writing multithreaded programs, see How to Use Threads .

Trail: Creating a GUI with JFC/Swing Lesson: Writing Event Listeners

How to Write a Window Listener


Window events are fired by a window (such as a frame or dialog ) just after the window is opened, closed, iconified, deiconified, activated, or deactivated. Opening a window means showing it for the first time; closing it means removing the window from the screen. Iconifying it means substituting a small icon on the desktop for the window; deiconifying means the opposite. A window is activated if it or a component it contains has the keyboard focus; deactivation occurs when the window and all of its contents lose the keyboard focus. If you want to be notified when a window is made visible or hidden, then you should register a component listener on the window.

The most common use of window listeners is implementing custom window-closing behavior. For example, you might use a window listener to save data before closing the window, or to exit the program when the last window closes. You don't necessarily need to implement a window listener to specify what a window should do when the user closes it. By default, when the user closes a window the window becomes invisible. You can specify different behavior -- disposing of the window, for example -- using the JFrame or JDialog setDefaultCloseOperation method. If you decide to implement a window-closing handler, then you might want to use setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE) to specify that your window listener takes care of all window-closing duties. See How to Make Frames (Main Windows) for an example of a handler for windowclosing events. Within that section, Responding to Window-Closing Events has details on how to use setDefaultCloseOperation. Another common use of window listeners is to stop threads and release resources when a window is iconified, and to start up again when the window is deiconified. This way, you can avoid unnecessarily using the processor or other resources. For example, when a window that contains animation is iconified, it should stop its animation thread and free any large buffers. When the window is deiconified, it can start the thread again and recreate the buffers. The following applet demonstrates window events. By clicking the top button in the applet, you can bring up a small window. The controlling class listens for window events from the window, displaying a message whenever it detects a window event. You can find the applet's code in WindowEventDemo.java .

This is a picture of the applet's GUI. To run the applet, click the picture. The applet will appear in a new browser window. Try this: 1. Bring up the Window Demo Window by clicking the applet's top button. The first time you click this button, you'll see a "Window opened" message in the applet's display area.

2. Click the window if it doesn't already have the focus. Do you see a "Window activated" message in the applet's display area? 3. Iconify the window, using the window controls. You'll see a "Window iconified" message in the applet's display area. 4. Deiconify the window. You'll see a "Window deiconified" message in the applet's display area. 5. Close the window, using the window controls. You'll see "Window closing" in the applet's display area. Because the windowclosing event handler invokes setVisible(false) instead of dispose(), you won't see "Window closed".

Here is the applet's window event handling code:


public class WindowEventDemo ... implements WindowListener { ...//where initialization occurs: //Create but don't show window. window = new JFrame("Window Event Window"); window.addWindowListener(this); window.getContentPane().add( new JLabel("The applet listens to this window " + "for window events."), BorderLayout.CENTER); window.pack(); } public void windowClosing(WindowEvent e) { window.setVisible(false); displayMessage("Window closing", e); } public void windowClosed(WindowEvent e) { displayMessage("Window closed", e); } public void windowOpened(WindowEvent e) { displayMessage("Window opened", e); } public void windowIconified(WindowEvent e) { displayMessage("Window iconified", e); } public void windowDeiconified(WindowEvent e) { displayMessage("Window deiconified", e); } public void windowActivated(WindowEvent e) { displayMessage("Window activated", e); } public void windowDeactivated(WindowEvent e) { displayMessage("Window deactivated", e);

} void displayMessage(String prefix, WindowEvent e) { display.append(prefix + ": " + e.getWindow() + newline); } ...

The Window Event API


The WindowListener interface and its corresponding adapter class, WindowAdapter , contain these methods:
void windowOpened(WindowEvent)

Called just after the listened-to window has been shown for the first time.
void windowClosing(WindowEvent)

void windowClosed(WindowEvent)

Called in response to a user request that the listened-to window be closed. To actually close the window, the listener should invoke the window's dispose or setVisible(false) method. Called just after the listened-to window has closed.

void windowIconified(WindowEvent) void windowDeiconified(WindowEvent)

Called just after the listened-to window is iconified or deiconified, respectively.


void windowActivated(WindowEvent) void windowDeactivated(WindowEvent)

Called just after the listened-to window is activated or deactivated, respectively. Each window event method has a single parameter: a WindowEvent object.
Window getWindow()

Returns the window that fired the event. You can use this instead of the getSource method.

Examples that Use Window Listeners


The following table lists the examples that use window listeners. Where Example Notes Described Reports all window events that occur on one WindowEventDemo This section window to demonstrate the circumstances under which window events are fired. One of many examples that listens for How to Make window closing events, so that the FrameDemo Frames (Main application can exit when its only window is Windows) closed. ComponentEventDemo How to Write a Listens for window-closing events on a Component frame displayed by an applet. This way, the Listener applet knows whether to re-open the

window when the user leaves and returns to the applet's page. How to Use Disposes a frame displayed by an applet FlowWindow FlowLayout when the user closes the frame. Listens for window iconify and deiconify How to Use SliderDemo events, so that it can stop the animation Sliders when the window isn't visible. Reports all internal frame events that occur How to Write an on one internal frame to demonstrate the InternalFrameEventDemo Internal Frame circumstances under which internal frame Listener events are fired. Internal frame events are similar to window events. General Rules Contains a text pane that requests the TextComponentDemo for Using Text keyboard focus in response to windowComponents activated events. Uses setDefaultCloseOperation instead General Rules of a window listener to determine what DialogDemo and for Using Text CustomDialog.java action to take when the user closes the Components window.

Trail: Creating a GUI with JFC/Swing Lesson: Using Swing Components

How to Make Frames (Main Windows)


A frame, implemented as an instance of the JFrame class, is a window that has decorations such as a border, a title, and buttons for closing and iconifying the window. Applications with a GUI typically use at least one frame. Applets sometimes use frames, as well. To make a window that's dependent on another window -- disappearing when the other window is iconified, for example -- use a dialog instead of a frame. To make a window that appears within another window, use an internal frame. Here are two pictures of an empty-looking frame, each taken on a different platform. Solaris Windows

Note: The decorations on a frame are platform-dependent. You cannot change the decorations on a frame.

The Example Explained


The following code creates and sets up the frame from the previous figure and makes it visible onscreen. You can find the whole program in FrameDemo.java .
public static void main(String s[]) { JFrame frame = new JFrame("FrameDemo");

frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); //...create a blank label, set its preferred size... frame.getContentPane().add(emptyLabel, BorderLayout.CENTER); frame.pack(); frame.setVisible(true); }

The first line of code creates a frame with the constructor that lets you set the frame's title. The only other constructor provided by JFrame is a no-argument constructor. Next the code adds a window listener to the frame. The listener's implementation makes the program exit when the user closes the frame. This behavior is appropriate for this program because the program has only one frame, and closing the frame makes the program useless. If the program didn't exit, then it would continue to run but have no visible GUI and no way of making any GUI visible. See Responding to Window-Closing Events for more information. The bold line in the code segment adds a blank label to the frame's content pane. If you're not already familiar with content panes and how to add components to them, please read Adding Components to the Content Pane. The next line gives the frame a size, using the pack method. The pack method sizes the frame so that all its contents are at or above their preferred sizes. An alternative to pack is to establish a frame's size explicitly by calling setSize. In general, using pack is preferable to calling setSize, since pack leaves the frame's layout manager in charge of the frame's size, and layout managers are good at adjusting to platform dependencies and other factors that affect component size.

The last line uses the setVisible method to make the frame appear onscreen. Sometimes you might see the show method used instead of setVisible(true). The two usages are equivalent, but we use setVisible(true) for consistency's sake. Note: If any part of the frame has been realized you should invoke setVisible from the event dispatching thread. For a definition of the term "realized" and information about the event dispatching thread, refer to Threads and Swing .

Responding to Window-Closing Events


By default, when the user closes a frame onscreen, the frame is hidden. Although invisible, the frame still exists and the program can make it visible again. If you want different behavior, then you need to either register a window listener that handles window-closing events, or you need to specify default close behavior using the setDefaultCloseOperation method. You can even do both. The argument to setDefaultCloseOperation must be one of the following values, which are defined in the WindowConstants interface (which JFrame implements):

-- Don't do anything when the user's requests that the frame close. Instead, the program should probably use a window listener that performs some other action in its windowClosing method. HIDE_ON_CLOSE (the default) -- Hide the frame when the user closes it. This removes the frame from the screen. DISPOSE_ON_CLOSE -- Hide and dispose of the frame when the user closes it. This removes the frame from the screen and frees up any resources used by it.
DO_NOTHING_ON_CLOSE

The default close operation is executed after the frame's window listeners (if any) handle the window-closing event. So, for example, assume that you specify that the default close operation is to dispose of the frame. You also implement a window listener that tests whether the frame is the last one and, if so, exits the application. Under these conditions, when the user closes a frame, the window listener will be called first. If it doesn't exit the application, then the default close operation -- disposing of the frame -- will then be performed. For more information about handling window-closing events, see How to Write a Window Listener . Besides handling window-closing events, window listeners can also react to other window state changes, such as iconification and activation.

The Frame API


The following tables list the commonly used JFrame constructors and methods. Other methods you're likely to call are defined by the java.awt.Frame and java.awt.Window classes, from which JFrame descends. These methods include pack, setSize, setVisible, setTitle, and getTitle.

Because each JFrame object has a root pane, frames have support for interposing input and painting behavior in front of the frame's children, placing children on different "layers", and for Swing menu bars. These topics are introduced in Using Top-Level Containers. and explained in detail in How to Use Root Panes. The API for using frames falls into these categories:

Creating and Setting Up a Frame Methods Related to the Root Pane Creating and Setting Up a Frame Purpose Create a frame that is initially invisible. Call setVisible(true) on the frame to make it visible. The String argument provides a title for the frame. You can also use setTitle to set a frame's title. Set or get the operation that occurs when the user pushes the close button on this frame. Possible choices are:

Method
JFrame() JFrame(String)

void setDefaultCloseOperation(int) int getDefaultCloseOperation()

DO_NOTHING_ON_CLOSE HIDE_ON_CLOSE (the default) DISPOSE_ON_CLOSE

These constants are defined in the WindowConstants interface, which JFrame implements. Methods Related to the Root Pane Method Purpose void setContentPane(Container) Set or get the frame's content pane. The content pane contains the frame's visible GUI components and Container getContentPane() should be opaque. Create, set, or get the frame's root pane. The root JRootPane createRootPane() void setRootPane(JRootPane) pane manages the interior of the frame including the JRootPane getRootPane() content pane, the glass pane, and so on. void setJMenuBar(JMenuBar) Set or get the frame's menu bar to manage a set of JMenuBar getJMenuBar() menus for the frame. void setGlassPane(Component) Set or get the frame's glass pane. You can use the Component getGlassPane() glass pane to intercept mouse events. Set or get the frame's layered pane. You can use the void setLayeredPane(JLayeredPane) frame's layered pane to put components on top of or JLayeredPane getLayeredPane() behind other components.

Examples that Use Frames


All of the examples in this trail that are standalone applications use JFrame. The following table lists a few and tells you where each is discussed. Where Example Notes Described The Example FrameDemo Displays a basic frame with one component. Explained A study in creating and destroying windows, in Framework -implementing a menu bar, and in exiting an application. A subclass of JFrame that adds components to the How to Use ColorChooserDemo Color Choosers default content pane. A subclass of JFrame that sets the frame's content How to Use TableDemo Tables pane. How to Use Illustrates how to use a layered pane (but not the LayeredPaneDemo Layered Panes frame's layered pane). GlassPaneDemo The Glass Pane Illustrates the use of a frame's glass pane. How to Use MenuDemo Shows how to put a JMenuBar in a JFrame. Menus
Trail: Creating a GUI with JFC/Swing Lesson: Using Swing Components

How to Use Color Choosers


Use the JColorChooser class to provide users with a palette of colors to choose from. A color chooser is a component that you can place anywhere within your program's GUI. The JColorChooser API also makes it easy to bring up a dialog (modal or not) that contains a color chooser. Here's a picture of an application that uses a color chooser to set the text color in a banner:

The source code for the program is in ColorChooserDemo.java . The color chooser consists of everything within the box labeled Choose Text Color. This is what a standard color chooser looks like in the Java Look & Feel. It contains two parts, a tabbed pane and a preview panel. The three tabs in the tabbed pane select chooser panels. The preview panel below the tabbed pane displays the currently selected color. Here's the code from the example that creates a JColorChooser instance and adds it to the demo's window:
final JLabel banner = new JLabel("Welcome to the Tutorial Zone!", JLabel.CENTER); banner.setForeground(Color.yellow); ... final JColorChooser tcc = new JColorChooser(banner.getForeground()); ... getContentPane().add(tcc, BorderLayout.CENTER); The ColorChooser constructor in the previous code snippet takes a Color argument,

which specifies the chooser's initially selected color. If you don't specify the initial color, then the color chooser displays Color.white. See the Color API documentation for a list of color constants you can use.

A color chooser uses an instance of ColorSelectionModel to contain and manage the current selection. The color selection model fires a change event whenever the user changes the color in the color chooser. The example program registers a change listener with the color selection model so that it can update the banner at the top of the window. The following code registers and implements the change listener:
tcc.getSelectionModel().addChangeListener( new ChangeListener() { public void stateChanged(ChangeEvent e) { Color newColor = tcc.getColor(); banner.setForeground(newColor); } } );

See How to Write a Change Listener for general information about change listeners and change events. A basic color chooser, like the one used in the example program, is sufficient for many programs. However, the color chooser API allows you to customize a color chooser by providing it with a preview panel of your own design, by adding your own chooser panels to it, or by removing existing chooser panels from the color chooser. Additionally, the JColorChooser class provides two methods that make it easy to use a color chooser within a dialog. The rest of this section discusses these topics:

Another Example: ColorChooserDemo2 Showing a Color Chooser in a Dialog Removing or Replacing the Preview Panel Creating a Custom Chooser Panel The Color Chooser API Examples that Use Color Choosers

Another Example: ColorChooserDemo2


Now turn your attention to ColorChooserDemo2.java , a modified version of the previous demo program that uses more of the JColorChooser API. In addition to the main source file, this example needs one other source file and the crayon images. See the examples index for links to all the files required by this example. Here's a picture of ColorChooserDemo2:

Additionally, this program customizes the banner's text color chooser in these ways:

Removes the preview panel Removes all of the default chooser panels Adds a custom chooser panel

Removing or Replacing the Preview Panel covers the first customization. Creating a Custom Chooser Panel discusses the last two. This program also adds a button that brings up a color chooser in a dialog, which you can use to set the banner's background color.

Showing a Color Chooser in a Dialog


The JColorChooser class provides two class methods to make it easy to use a color chooser in a dialog. ColorChooserDemo2 uses one of these methods, showDialog, to display the background color chooser when the user clicks the Show Color Chooser... button. Here's the single line of code from the example that brings up the background color chooser in a dialog:
Color newColor = JColorChooser.showDialog( ColorChooserDemo2.this, "Choose Background Color", banner.getBackground());

The first argument is the parent for the dialog, the second is the dialog's title, and the third is the initially selected color. The dialog disappears under three conditions: the user chooses a color and clicks the OK button, the user cancels the operation with the Cancel button, or the user dismisses the dialog with a frame control. If the user chooses a color, the showDialog method returns the new color. If the user cancels the operation or dismisses the window, the method returns null. Here's the code from the example that updates the banner's background color according to the value returned by showDialog:
if (newColor != null) { banner.setBackground(newColor); } The dialog created by showDialog is modal. If you want a non-modal dialog, you can use JColorChooser's createDialog method to create the dialog. This method also lets you

specify action listeners for the OK and Cancel buttons in the dialog window. Use JDialog's show method to display the dialog created by this method. For an example that uses this method, see Specifying Other Editors in the How to Use Tables section.

Removing or Replacing the Preview Panel


By default, the color chooser displays a preview panel. The example program removes the text color chooser's preview panel with this line of code:
tcc.setPreviewPanel(new JPanel());

This effectively removes the preview panel because a plain JPanel has no size and no default view. To set the preview panel back to the default, use null as the argument to setPreviewPanel. To provide a custom preview panel, you also use setPreviewPanel. The component you pass into the method should inherit from JComponent, specify a reasonable size, and provide a customized view of the current color. To get notified when the user changes the color in the color chooser, the preview panel must register as a change listener on the color chooser's color selection model as described previously.

Creating a Custom Chooser Panel


The default color chooser provides three chooser panels:

Swatches -- for choosing a color from a collection of swatches. HSB -- for choosing a color using the Hue-Saturation-Brightness color model. RGB -- for choosing a color using the Red-Green-Blue color model.

You can extend the default color chooser by adding chooser panels of your own design with addChooserPanel, or you can limit it by removing chooser panels with removeChooserPanel.

If you want to remove all of the default chooser panels and add one or more of your own, you can do this with a single call to setChooserPanels. ColorChooserDemo2 uses this method to replace the default chooser panels with an instance of CrayonPanel , a custom chooser panel. Here's the call to setChooserPanels from that example:
//Override the chooser panels with our own. AbstractColorChooserPanel panels[] = { new CrayonPanel() }; tcc.setChooserPanels(panels); The code is straighforward: it creates an array containing the CrayonPanel. Next the code calls setChooserPanels to set the contents of the array as the color chooser's

chooser panels. is a subclass of AbstractColorChooserPanel and overrides the five abstract methods defined in its superclass:
CrayonPanel void buildChooser()

Creates the GUI that comprises the chooser panel. The example creates four toggle buttons -- one for each crayon -- and adds them to the chooser panel.
void updateChooser()

This method is called whenever the chooser panel is displayed. The example's implementation of this method selects the toggle button that represents the currently selected color.
public void updateChooser() { Color color = getColorFromModel(); if (color.equals(Color.red)) { redCrayon.setSelected(true); } else if (color.equals(Color.yellow)) { yellowCrayon.setSelected(true); } else if (color.equals(Color.green)) { greenCrayon.setSelected(true); } else if (color.equals(Color.blue)) { blueCrayon.setSelected(true); } } String getDisplayName()

Returns the display name of the chooser panel. The name is used on the tab for the chooser panel. Here's the example's getDisplayName method:
public String getDisplayName() { return "Crayons"; } Icon getSmallDisplayIcon()

Returns a small icon to represent this chooser panel. This is currently unused. Future versions of the color chooser might use this icon or the large one to represent this chooser panel in the display. The example's implementation of this method returns null.
Icon getLargeDisplayIcon()

Returns a large icon to represent this chooser panel. This is currently unused. Future versions of the color chooser might use this icon or the small one to

represent this chooser panel in the display. The example's implementation of this method returns null.

The Color Chooser API


The following tables list the commonly used JColorChooser constructors and methods. Other methods you might call are listed in the API tables in The JComponent Class. The API for using color choosers falls into these categories:

Creating and Displaying the Color Chooser Customizing the Color Chooser's GUI Setting or Getting the Current Color

Creating and Displaying the Color Chooser Method Purpose Create a color chooser. The default constructor creates a color chooser with an initial color of Color.white. Use the second JColorChooser() JColorChooser(Color) constructor to specify a different initial color. JColorChooser(ColorSelectionModel) The ColorSelectionModel argument, when present, provides the color chooser with a color selection model. Create and show a color chooser in a modal dialog. The Component argument is the Color showDialog(Component, String, dialog's parent, the String argument Color) specifies the dialog's title, and the Color argument specifies the chooser's initial color. Create a dialog for the specified color chooser. As with showDialog, the JDialog createDialog(Component, Component argument is the dialog's parent String, and the String argument specifies the boolean, dialog's title. The other arguments are as JColorChooser, ActionListener, follows: the boolean specifies whether the ActionListener) dialog is modal, the JColorChooser is the color chooser to display in the dialog, the first ActionListener is for the OK button, and the second is for the Cancel button. Customizing the Color Chooser's GUI Method Purpose void setPreviewPanel(JComponent) Set or get the component used JComponent getPreviewPanel() to preview the color selection. To remove the preview panel, use new JPanel() as an

argument. To specify the default preview panel, use null.


void setChooserPanels(AbstractColorChooserPanel[]) AbstractColorChooserPanel[] getChooserPanels() void addChooserPanel(AbstractColorChooserPanel) AbstractColorChooserPanel removeChooserPanel(AbstractColorChooserPanel)

Set or get the chooser panels in the color chooser.

Add a chooser panel to the color chooser or remove a chooser panel from it. Setting or Getting the Current Color Method Purpose Set or get the currently selected color. The three integer version of the setColor method interprets the three integers void setColor(Color) together as an RGB color. The single void setColor(int, int, int) integer version of the setColor method void setColor(int) Color getColor() divides the integer into four 8-bit bytes and interprets the integer as an RGB color as follows: Set or get the selection model for the color chooser. This object contains the void setSelectionModel(ColorSelectionModel) current selection and fires change events ColorSelectionModel getSelectionModel() to registered listeners whenever the selection changes.

Examples that Use Color Choosers


This table shows the examples that use JColorChooser and where those examples are described. Where Example Notes Described ColorChooserDemo This section Uses a standard color chooser. Uses one customized color chooser and one ColorChooserDemo2 This section standard color chooser in a dialog created with showDialog. Shows how to use a color chooser as a custom cell How to Use TableDialogEditDemo editor in a table. The color chooser used by this Tables example is created with createDialog.
Trail: Creating a GUI with JFC/Swing Lesson: Using Swing Components

How to Use Layered Panes

A layered pane is a Swing container that provides a third dimension for positioning components: depth, also known as Z order. When adding a component to a layered pane, you specify its depth as an integer. The higher the number, the higher the depth. If components overlap, components at a higher depth are drawn on top of components at a lower depth. The relationship between components at the same depth is determined by their positions within the depth. Every Swing container that has a root pane -- such as JFrame, JApplet, JDialog, or JInternalFrame -- automatically has a layered pane. Most programs don't explicitly use the root pane's layered pane, so we don't discuss it in this section. You can find information about it in The Root Pane, which provides an overview, and The Layered Pane, which has further details. This section concentrates on telling you how to create your own layered pane and use it anywhere you might use a regular Swing container. Swing provides two layered pane classes. The first, JLayeredPane , is the class that root panes use and is the class used by the example in this section. The second, JDesktopPane, is a JLayeredPane subclass that's specialized for the task of holding internal frames. For examples of using JDesktopPane, see How to Use Internal Frames. Here's a picture of an application that creates a layered pane and places overlapping, colored labels at different depths:

Try this:

1. Compile and run the application. The source file is LayeredPaneDemo.java . You will also need the dukeWaveRed.gif image file. See Getting Started with Swing if you need help compiling or running this application. 2. Move the mouse around in the lower part of the window. The image of Duke drags behind the green and red labels, but in front of the other three labels. 3. Use the combo box at the top of the window to change Duke's depth. Use the check box to set whether Duke is in the top position -- position 0 -- within the current depth. Here's the code from the example program that creates the layered pane:
layeredPane = new JLayeredPane(); layeredPane.setPreferredSize(new Dimension(300, 310)); layeredPane.setBorder(BorderFactory.createTitledBorder( "Move the Mouse to Move Duke")); layeredPane.addMouseMotionListener(new MouseMotionAdapter() { ... }); The code uses JLayeredPane's only constructor -- the no-argument constructor -- to

create the layered pane. The rest of the code uses methods inherited from superclasses to give the layered pane a preferred size and a border, and add a mouse-motion listener to it. The mouse-motion listener just moves the Duke image around in response to mouse movement. Ultimately, the example adds the layered pane to the frame's content pane:
Container contentPane = getContentPane(); ... contentPane.add(layeredPane);

As we'll show you a bit later, you add components to a layered pane using an add method. When adding a component to a layered pane, you specify the component's depth, and optionally, its position within its depth. The layered pane in the demo program contains six labels -- the five colored labels and a sixth one that displays the Duke image. As the program demonstrates, both the depth of a component and its position with that depth can change dynamically. The rest of this section covers these topics:

Adding Components and Setting Component Depth Setting a Component's Position Within Its Depth Laying Out Components in a Layered Pane The Layered Pane API Examples that Use Layered Panes

Adding Components and Setting Component Depth


Here's the code from the sample program that adds the colored labels to the layered pane:
for (int i = 0; i < ...number of labels...; i++) {

JLabel label = createColoredLabel(...); layeredPane.add(label, new Integer(i)); ...

You can find the implementation of the createColoredLabel method in the source code for the program. It just creates an opaque JLabel initialized with a background color, a border, some text, and a size. The example program uses a two-argument version of the add method. The first argument is the component to add, the second is an Integer object, specifying the depth. This program uses the for loop's iteration variable to specify depths. The actual values don't matter much. What matters is the relative value of the depths and that you are consistent within your program in how you use each depth. Note: If you use the root pane's layered pane, be sure to use its depth conventions. Refer to The Layered Pane for details. That section shows you how to modify LayeredPaneDemo to use the root pane's layered pane. With the modifications, you can see how the dragging Duke image relates to the combo box in the control panel. As you can see from the example program, if components overlap, components at a higher depth are on top of components at a lower depth. To change a component's depth dynamically, use the setLayer method. In the example, the user can change Duke's layer by making a selection from the combo box. Here's the actionPerformed method of the action listener registered on the combo box:
public void actionPerformed(ActionEvent e) { int position = onTop.isSelected() ? 0 : 1; layeredPane.setLayer(dukeLabel, layerList.getSelectedIndex(), position); } The setLayer method used here takes three arguments: the component whose depth is be set, the new depth, and the position within the depth. JLayeredPane has a twoargument version of setLayer that takes only the component and the new depth. That

to

method puts the component at the bottom position in its depth. A note of caution: When adding a component to a layered pane you specify the layer with an Integer. When using setLayer to change a component's layer, you use an int. You might think that if you use an int instead of an Integer with the add method, the compiler would complain or your program would throw an illegal argument exception. But the compiler says nothing, which results in a common layered pane problem. You can use the API tables at the end of this section to check the types of the arguments and return values for methods that deal with layers.

Setting a Component's Position Within Its Depth


The following code creates the label that displays Duke's image, and then adds the label to the layered pane.
final ImageIcon icon = new ImageIcon("images/dukeWaveRed.gif");

... dukeLabel = new JLabel(icon); dukeLabel.setBounds(15, 225, icon.getIconWidth(), icon.getIconHeight()); layeredPane.add(dukeLabel, new Integer(2), 0); This code uses the three-argument version of the add method.

The third argument specifies the Duke label's position within its depth, which determines the component's relationship with other components at the same depth. Positions are specified with an int between -1 and (n - 1), where n is the number of components at the depth. Unlike layer numbers, the smaller the position number, the higher the component within its depth. Using -1 is the same as using n - 1; it indicates the bottom-most position. Using 0 specifies that the component should be in the top-most position within its depth. As the following figure shows, with the exception of -1, a lower position number indicates a higher position within a depth.

A component's position within its layer can change dynamically. In the example, you can use the check box to determine whether Duke label is in the top position at its depth. Here's the actionPerformed method for the action listener registered on the check box:
public void actionPerformed(ActionEvent e) { if (onTop.isSelected()) layeredPane.moveToFront(dukeLabel); else layeredPane.moveToBack(dukeLabel); } When the user selects the check box, the moveToFront method

moves Duke to the front (position 0). And when the user deselects check box, Duke gets moved to the back with the moveToBack method. You can also use the setPosition method or the threeargument version of setLayer to change a component's position.

Laying Out Components in a Layered Pane


By default a layered pane has no layout manager. This means that you typically have to write the code that positions and sizes the components you put in a layered pane. The example uses the setBounds method to set the size and position of each of the labels:
dukeLabel.setBounds(15, 225, icon.getIconWidth(), icon.getIconHeight()); ... label.setBounds(origin.x, origin.y, 140, 140);

When the user moves the mouse around, the program calls setPosition to change Duke's position:
dukeLabel.setLocation(e.getX()-XFUDGE, e.getY()-YFUDGE);

Although a layered pane has no layout manager by default, you can still assign a layout manager to the layered pane. All of the layout managers provided by the Java platform arrange the components as if they were all on one layer. Here's a version of the previous demo that sets the layered pane's layout manager to an instance of GridLayout, using that layout manager to lay out six colored labels.

You can find the code for this program in LayeredPaneDemo2.java . This program also needs the dukeWaveRed.gif image file. Many programs use intermediate containers (such as panels) and their layout managers to lay out components on the same layer, but use absolute positioning to lay out components on different layers. For more information about absolute positioning, see Doing Without a Layout Manager (Absolute Positioning) .

The Layered Pane API


The following tables list the commonly used JLayeredPane constructors and methods. Other methods you are most likely to invoke on a JLayeredPane object are those it inherits from its superclasses, such as setBorder, setPreferredSize, and so on. See The JComponent API for tables of commonly used inherited methods. The API for using layered pane falls into these categories:

Creating or Getting a Layered Pane Layering Components Setting Component's Intra-Layer Positions

Method
JLayeredPane()

Creating or Getting a Layered Pane Purpose Create a layered pane. Get the automatic layered pane in an applet, dialog, frame, or internal frame.

JLayeredPane getLayeredPane() (in JApplet, JDialog, JFrame, and JInternalFrame)

Layering Components Method Purpose Add the specified component to the layered pane. The second argument, when present, indicates the layer. The third argument, when present, indicates void add(Component) the component's position within its layer. If you use void add(Component, Integer) the one-argument version of this method, the void add(Component, Integer, component is added to layer 0. If you use the oneint) or two-argument version of this method, the component is placed underneath all other components currently in the same layer. Change the component's layer. The second void setLayer(Component, int) argument indicates the layer. The third argument, void setLayer(Component, int, when present, indicates the component's position int) within its layer.
int getLayer(Component) int getLayer(JComponent) int getComponentCountInLayer(int)

Get the layer for the specified component.

Get the number of components in the specified layer. The value returned by this method can be useful for computing position values. Component[] Get an array of all the components in the specified getComponentsInLayer(int) layer. int highestLayer() Compute the highest or lowest layer currently in int lowestLayer() use. Setting Components' Intra-Layer Positions Method Purpose
void setPosition(Component, int) int getPosition(Component) void moveToFront(Component) void moveToBack(Component)

Set or get the position for the specified component within its layer. Move the specified component to the front or back of its layer.

Examples that Use Layered Panes


This table shows the examples that use JLayeredPane and where those examples are described.

Example

Notes Illustrates layers and intra-layer positions of a LayeredPaneDemo This section JLayeredPane. Uses a layout manager to help lay out the LayeredPaneDemo2 This section components in a layered pane. The description describes how to change No source provided The Layered Pane LayeredPaneDemo to use the root pane's layered pane. How to Use Internal Uses a JDesktopFrame to manage internal InternalFrameDemo Frames frames. Moving an Image Animates a rocketship using layers in a MovingLabels Across the Screen layered pane.
Trail: Creating a GUI with JFC/Swing Lesson: Using Swing Components

Where Described

How to Use Root Panes


In general, you don't directly create a JRootPane object. Instead, you get a JRootPane (whether you want it or not!) when you instantiate JInternalFrame or one of the toplevel Swing containers, such as JApplet, JDialog, and JFrame. Using Top-Level Containers tells you the basics of using root panes -- getting the content pane, setting its layout manager, and adding Swing components to it. This section tells you more about root panes, including the components that make up a root pane and how you can use them. Another place to get information about root panes is The Swing Connection, especially the article Understanding Containers.

As the preceding figure shows, a root pane has four parts: The glass pane Hidden, by default. If you make the glass pane visible, then it's like a sheet of glass over all the other parts of the root pane. It's completely transparent unless you implement the glass pane's paint method so that it does something, and it intercepts input events for the root pane. In the next section, you'll see an example of using a glass pane. The layered pane

Serves to position its contents, which consist of the content pane and the optional menu bar. Can also hold other components in a specified Z order. For information, see The Layered Pane. The content pane The container of the root pane's visible components, excluding the menu bar. For information on using the content pane, see Using Top-Level Containers. The optional menu bar The home for the root pane's container's menus. If the container has a menu bar, you generally use the container's setJMenuBar method to put the menu bar in the appropriate place. For more information on using menus and menu bars, see How to Use Menus.

The Glass Pane


The glass pane is useful when you want to be able to catch events or paint over an area that already contains one or more components. For example, you can deactivate mouse events for a multi-component region by having the glass pane intercept the events. Or you can display an image over multiple components using the glass pane. Here's a picture of an application that demonstrates glass pane features. It contains a check box that lets you set whether the glass pane is "visible" -- whether it can get events and paint itself onscreen. When the glass pane is visible, it blocks all input events from reaching the components in the content pane. It also paints a red dot in the place where it last detected a mouse-pressed event.

Try this: 1. Compile and run the application. The source file is GlassPaneDemo.java . See Getting Started with Swing if you need help compiling or running this application. 2. Click Button 1. The button's appearance changes to show that it's been clicked. 3. Click the check box so that the glass pane becomes "visible," and then click Button 1 again. The button does not detect the mouse-pressed event because the glass pane intercepts it. When the glass pane detects the event, it beeps and paints a red circle where you clicked. 4. Click the check box again so that the glass pane is hidden. When the root pane detects an event over the check box, it forwards it to the check box. Otherwise, the check box would not respond to clicks.

The following code from GlassPaneDemo.java shows and hides the glass pane. This program happens to create its own glass pane, setting it using the JFrame setGlassPane method. However, if a glass pane doesn't do any painting, the program might simply attach listeners to the default glass pane, as returned by getGlassPane.
...//where GlassPaneDemo's UI is initialized: JCheckBox changeButton = new JCheckBox("Glass pane \"visible\""); changeButton.setSelected(false); changeButton.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { myGlassPane.setVisible(e.getStateChange() == ItemEvent.SELECTED); } });

The next code snippet implements the mouse-event handling for the glass pane. If a mouse event occurs over the check box or menu bar, then the glass pane redispatches the event so that the check box or menu component receives it. So that the check box and menu behave properly, they also receive all drag events that started with a press in the button or menu bar.
...//In the implementation of the glass pane's mouse listener: public void mouseMoved(MouseEvent e) { redispatchMouseEvent(e, false); } .../* The mouseDragged, mouseClicked, mouseEntered, * mouseExited, and mousePressed methods have the same * implementation as mouseMoved*/... public void mouseReleased(MouseEvent e) { redispatchMouseEvent(e, true); inDrag = false; } private void redispatchMouseEvent(MouseEvent e, boolean repaint) { boolean inButton = false; boolean inMenuBar = false; Point glassPanePoint = e.getPoint(); Component component = null; Container container = contentPane; Point containerPoint = SwingUtilities.convertPoint( glassPane, glassPanePoint, contentPane); int eventID = e.getID(); if (containerPoint.y < 0) { inMenuBar = true; //...set container and containerPoint accordingly... testForDrag(eventID); }

component = SwingUtilities.getDeepestComponentAt( container, containerPoint.x, containerPoint.y); if (component.equals(liveButton)) { inButton = true; testForDrag(eventID); } if (inMenuBar || inButton || inDrag) { ...//Redispatch the event to component... } if (repaint) { toolkit.beep(); glassPane.setPoint(glassPanePoint); glassPane.repaint(); }

private void testForDrag(int eventID) { if (eventID == MouseEvent.MOUSE_PRESSED) { inDrag = true; } }

Here is the code that implements the painting for the glass pane:
...//where GlassPaneDemo's UI is initialized: myGlassPane = new MyGlassPane(...); frame.setGlassPane(myGlassPane); ... /** * We have to provide our own glass pane so that it can paint. */ class MyGlassPane extends JComponent { Point point = null; public void paint(Graphics g) { if (point != null) { g.setColor(Color.red); g.fillOval(point.x - 10, point.y - 10, 20, 20); } } ...

The Layered Pane


A root pane places its menu bar and content pane in an instance of JLayeredPane--a container with depth--such that overlapping components can appear one on top of the other. This is useful for displaying popup menus above other components, for example. Your programs can also put components in the root pane's layered pane. If you do, then you should be aware that certain depths are defined to be used for specific functions, and

you should use the depths as intended. Otherwise, your components might not play well with the others. Here's a diagram that shows the functional layers and their relationship:

The table below describes the intended use for each layer and the named constant defined in the JLayeredPane class that corresponds to it: Layer Name Value Description This layer is used to position the frame's content pane and menu bar. Most programs won't use this. The root pane adds the menu bar and content pane to its layered pane at this depth.

FRAME_CONTENT_LAYER

new Integer(30000)

DEFAULT_LAYER new Integer(0)

Most components go in this layer. If you don't specify a component's depth, the layered pane puts it at this depth. This layer is useful for floating toolbars and palettes. Modal internalframe dialogs would belong in this layer. Popups go in this layer because they need to appear above just about everything. Move a component to this layer when

PALETTE_LAYER new Integer(100)

MODAL_LAYER

new Integer(200)

POPUP_LAYER

new Integer(300)

DRAG_LAYER

new Integer(400)

dragging. Return the component to its regular layer when dropped. This tutorial does not provide an example of using the root pane's layered pane. However, by modifying a few lines of code in the example described in How to Use Layered Panes, you can make the program use the root pane's layered pane instead of creating one. The left column in this table shows the code as it appears in LayeredPaneDemo.java . The right column shows how to change it: From... To...
layeredPane = new JLayeredPane(); layeredPane = getLayeredPane(); final int YFUDGE = 57; contentPane.add(layeredPane); frame.pack(); final int YFUDGE = 27; //contentPane.add(layeredPane); frame.setSize(new Dimension(350, 400)); Point origin = new Point(10, 20); Point origin = new Point(10, 70);

Because the program now uses the root pane's layered pane, the Duke label can be dragged all around inside the window and over the components in the control panel. What do you suppose happens when you bring up the combo box? Will Duke be under the combo box's menu or over it?

Notice that the layered pane's mouse listener is not notified of events when the mouse is over the combo box or the checkbox.

The Root Pane API


The tables that follow list the API for using root panes, glass panes, and content panes. For more information on using content panes, go to Using Top-Level Containers. Here are the tables in this section:

Using a Root Pane Setting or Getting the Glass Pane Setting or Getting the Content Pane

The API for using other parts of the root pane is described elsewhere:

The Layered Pane API The Menu API Using a Root Pane Purpose Get the root pane of the applet, dialog, frame, internal frame, or window. If the component contains a root pane, returns that root pane. Otherwise, returns the root pane (if any) that contains the component. Invokes the SwingUtilities getRootPane method on the JComponent.

Method
JRootPane getRootPane() (in JApplet, JDialog, JFrame, JInternalFrame, and JWindow)

JRootPane SwingUtilities.getRootPane(Component)

JRootPane getRootPane() (in JComponent)

Set or get which button (if any) is the default button in the root pane. A lookvoid setDefaultButton(JButton) and-feel-specific action, such as pressing JButton getDefaultButton() Enter, causes the button's action to be performed. Setting or Getting the Glass Pane Method Purpose
setGlassPane(Component) Component getGlassPane() (in JApplet, JDialog, JFrame, JInternalFrame, JRootPane, and JWindow)

Sets or gets the glass pane.

Setting or Getting the Content Pane Method Purpose

setContentPane(Container) Container getContentPane() (in JApplet, JDialog, JFrame, JInternalFrame, JRootPane, and JWindow)

Set or get the content pane.

Examples that Use Root Panes


Every Swing program has a root pane, but few reference it directly. The examples in the following list illustrate how to use features of JRootPane or the glass pane. Also see these lists:

Examples that Use Layered Panes Examples that Use Menus Examples that Use Frames (for examples of using content panes) Notes Uses a glass pane. Redispatches events. Sets the default button for a top-level container, using the root pane's setDefaultButton method. Sets a property on the root pane, to try to avoid a security check that can cause disturbing messages in the console in JDK 1.1.

Where Described GlassPaneDemo This section How to Use ListDialog BoxLayout Example
AppletDemo

How to Make Applets

Trail: 2D Graphics
by Deborah Adair, Jennifer Ball and Monica Pawlan
Your feedback is important to us! Please send your comments and suggestions to us using the feedback page. This trail introduces you to the Java 2D API and shows you how to display and print 2D graphics in your Java programs. The Java 2D API enables you to easily

Draw lines of any thickness Fill shapes with gradients and textures Move, rotate, scale, and shear text and graphics Composite overlapping text and graphics

For example, you could use the Java 2D API to display complex charts and graphs that use various line and fill styles to distinguish sets of data, like those shown in the following figure.

The Java 2D API also enables you to store and to manipulate image data--for example, you can easily perform image-filter operations, such as blur and sharpen, as shown in the following figure.

This trail covers the most common uses of the Java 2D APIs and briefly describes some of the more advanced features. For additional information about using the Java 2D APIs, see the Java 2D Programmer's Guide . Additional sample programs illustrating the Java 2D API features are also available online . Note: The sample applets in this trail can be run with the JDK 1.2 Applet Viewer, a browser with Java Plug-in 1.2 installed, or a JDK 1.2 compatible browser. The Java 2D APIs are closely integrated with the Abstract Windowing Toolkit (AWT). If you are not familiar with AWT, you might find it useful to review the AWT documentation, which you can download. Overview of the Java 2D API introduces the key Java 2D concepts and describes the Java 2D rendering model. Displaying Graphics with Graphics2D teaches you how to set up the Graphics2D rendering context to use fancy stroke and fill styles, perform transformations, clip the drawing region, composite overlapping graphics, and specify rendering preferences. Working with Text and Fonts shows you how to use a Font object to create a font with desired attributes, and to derive a new font by changing the attributes, determine the names of the fonts that are available on your system and position text within a component. Manipulating and Displaying Images his lesson explains how to implement double buffering and how to perform image-filter operations with BufferedImage objects. Printing teaches you how to render 2D graphics to a printer and how to print complex documents. Solving Common 2D Graphics Problems gives the solutions to some problems you might encounter when writing 2D applets and applications.

Trail: Creating a GUI with JFC/Swing

Lesson: Swing Features and Concepts


This lesson introduces Swing's features and explains all the concepts you need to be able to use Swing components effectively. At the end of this lesson we dissect a Swing program, as a means of reviewing everything you've learned.

Swing Components and the Containment Hierarchy


Swing provides many standard GUI components such as buttons, lists, menus, and text areas, which you combine to create your program's GUI. It also includes containers such as windows and tool bars.

Layout Management
Containers use layout managers to determine the size and position of the components they contain. Borders affect the layout of Swing GUIs by making Swing components larger. You can also use invisible components to affect layout.

Event Handling
Event handling is how programs respond to external events, such as the user pressing a mouse button. Swing programs perform all their painting and event handling in the eventdispatching thread.

Painting
Painting means drawing the component on-screen. Although it's easy to customize a component's painting, most programs don't do anything more complicated than customizing a component's border.

Threads and Swing


If you do something to a visible component that might depend on or affect its state, then you need to do it from the event-dispatching thread. This isn't an issue for many simple programs, which generally refer to components only in event-handling code. However, other programs need to use the invokeLater method to execute component-related calls in the event-dispatching thread.

More Swing Features and Concepts


Swing offers many features, many of which rely on support provided by the JComponent class. Some of the interesting features this lesson hasn't discussed yet include support for

icons, actions, Pluggable Look & Feel technology, assistive technologies, and separate models.

The Anatomy of a Swing-Based Program


A sample Swing application named Converter shows how Swing programs work and how the code hangs together.

Trail: Creating a GUI with JFC/Swing Lesson: Getting Started with Swing

Compiling and Running Swing Programs


This section tells you how to compile and run a Swing application. The compilation instructions work for all Swing programs -- applets, as well as applications. If you're interested in Swing applets, you should also read Running Swing Applets. If you aren't yet interested in compiling and running Swing programs, you can skip directly to A Quick Tour of a Swing Application's Code, which guides you through the code for a simple application. The instructions in this section assume that you're already comfortable with writing and compiling programs that use the Java platform. If you aren't, please go to the Getting Started trail. In particular, you'll need to successfully follow the instructions in The "Hello World" Application before you attempt to compile and run any Swing programs. How you compile and run Swing programs depends on whether you're using JDK 1.1 or the Java 2 Platform. Using the Java 2 Platform is a bit simpler because Swing is built into it. Choose the instructions corresponding to the release you're using:

Java 2 Platform, v 1.2 or 1.3 JDK 1.1 + JFC/Swing Release

Both instructions tell you how to run a simple program, called SwingApplication, whose GUI looks like this:

Trail: Creating a GUI with JFC/Swing Lesson: Getting Started with Swing

A Quick Tour of a Swing Application's Code


This section takes you through the code for the SwingApplication program. The next lesson, Swing Features and Concepts , provides full explanations of the topics introduced in this section. It also provides a bigger, more realistic example that you can use to expand and test your Swing knowledge.
SwingApplication

brings up a window that looks like this:

Each time the user clicks the button, the label is updated. You can find the whole program in SwingApplication.java . The code in SwingApplication.java accomplishes the following tasks:

Importing Swing packages Choosing the look and feel Setting up the top-level container Setting up buttons and labels Adding components to containers Adding borders around components Handling events Dealing with thread issues Supporting assistive technologies

Importing Swing Packages


The following line imports the main Swing package:
import javax.swing.*;

Note: Early JFC 1.1 and Java 2 SDK v 1.2 beta releases used different names for the Swing packages. See Swing Package Names for details. Most Swing programs also need to import the two main AWT packages:
import java.awt.*; import java.awt.event.*;

Choosing the Look and Feel


Swing allows you to specify which look and feel your program uses -- Java look and feel, Windows look and feel, CDE/Motif look and feel, and so on. The bold code in the following snippet shows you how SwingApplication specifies the look and feel:
public static void main(String[] args) { try { UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName()); } catch (Exception e) { } ...//Create and show the GUI... }

The preceding code essentially says, "I don't care whether the user has chosen a look and feel -- use the cross-platform look and feel (the Java look and feel)." You already know what the Java look and feel looks like, since almost all of our screenshots show it. For more information on specifying the look and feel, see How to Set the Look and Feel .

Setting Up the Top-Level Container


Every program that presents a Swing GUI contains at least one top-level Swing container. For most programs, the top-level Swing containers are instances of JFrame, JDialog, or (for applets) JApplet. Each JFrame object implements a single main window, and each JDialog implements a secondary window. Each JApplet object implements an applet's display area within a browser window. A top-level Swing container provides the support that Swing components need to perform their painting and event handling. The SwingApplication example has only one top-level container, a JFrame. When the user closes the frame, the application exits. Here is the code that sets up and shows the frame:
public class SwingApplication { ... public static void main(String[] args) { ... JFrame frame = new JFrame("SwingApplication"); //...create the components to go into the frame... //...stick them in a container named contents... frame.getContentPane().add(contents, BorderLayout.CENTER); //Finish setting up the frame, and show it. frame.addWindowListener(...); frame.pack(); frame.setVisible(true);

} }

For more information about top-level containers, see Swing Components and the Containment Hierarchy .

Setting Up Buttons and Labels


Like most GUIs, the SwingApplication GUI contains a button and a label. (Unlike most GUIs, that's about all that SwingApplication contains.) Here's the code that initializes the button:
JButton button = new JButton("I'm a Swing button!"); button.setMnemonic(KeyEvent.VK_I); button.addActionListener(...create an action listener...);

The first line creates the button. The second sets the I key as the mnemonic that the user can use to simulate a click of the button. For example, in the Java look and feel, typing Alt-i results in a button click. The third line registers an event handler for the button click. You'll see the event-handling code for this program in Handling Events. Here's the code that initializes and manipulates the label:
...//where instance variables are declared: private static String labelPrefix = "Number of button clicks: "; private int numClicks = 0; ...//in GUI initialization code: final JLabel label = new JLabel(labelPrefix + "0 ... label.setLabelFor(button); ...//in the event handler for button clicks: label.setText(labelPrefix + numClicks); ");

The preceding code is pretty straightforward, except for the line that invokes the setLabelFor method. That code exists solely to hint to assistive technologies that the label describes the button. For more information, see Supporting Assistive Technologies. For more information about Swing components such as buttons and labels, see Using Swing Components .

Adding Components to Containers


groups the label and button in a container (a JPanel) before adding the components to the frame. Here's the code that initializes the panel:
SwingApplication JPanel pane = new JPanel(); pane.setBorder(BorderFactory.createEmptyBorder(30, 30, 10, 30)); pane.setLayout(new GridLayout(0, 1)); pane.add(button); pane.add(label);

The first line of code creates the panel. The second line adds a border to it. We'll discuss the border later.

The third line of code creates a layout manager that forces the panel's contents to be displayed in a single column. The last lines add the button and label to the panel. Adding the button and label to the panel means they are controlled by the panel's layout manager. Specifically, a container's layout manager determines the size and position of each component that's been added to the container. Layout management concepts are discussed in Layout Management . To learn how to use individual layout managers, see Laying Out Components Within a Container .

Adding Borders Around Components


Here, again, is the code that adds a border to the panel:
pane.setBorder(BorderFactory.createEmptyBorder( 30, //top 30, //left 10, //bottom 30) //right );

This border simply provides some empty space around the panel's contents -- 30 extra pixels on the top, left, and right, and 10 extra pixels on the bottom. Borders are a feature that JPanel inherits from the JComponent class. Border concepts are discussed in Layout Management and Painting . See How to Use Borders for information about using the border API.

Handling Events
The SwingApplication example contains two event handlers. One handles button clicks (action events); the other handles window closing (window events). Here is the eventhandling code from SwingApplication:
button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { numClicks++; label.setText(labelPrefix + numClicks); } }); ... frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } });

You can read about Swing event handling in Event Handling and Writing Event Listeners .

Dealing with Thread Issues


The SwingApplication program is thread safe. Once its GUI is visible, its only GUI manipulation (updating the label) occurs in an event handler. Because the event handler

runs in the same thread that performs all event handling and painting for the application, there's no possibility that two threads will try to manipulate the GUI at once. However, it can be all too easy to introduce thread problems into a program. See Threads and Swing for information about thread safety in Swing.

Supporting Assistive Technologies


Support for assistive technologies -- devices such as screen readers that provide alternate ways of accessing information in a GUI -- is already included in every Swing component. The only code in SwingApplication that exists solely to support assistive technologies is this:
label.setLabelFor(button);

Assistive technologies can get plenty of information from Swing components, without any special code from you. For example, assistive technologies can automatically get the text information set by the following lines of code:
JButton button = new JButton("I'm a Swing button!"); label = new JLabel(labelPrefix + "0 "); label.setText(labelPrefix + numClicks); JFrame frame = new JFrame("SwingApplication");

See How to Support Assistive Technologies for more information about how you can ensure that your programs work well with tools that use the Accessibility API to query components.

Article

Mixing heavy and light components


Print-friendly Version

By Amy Fowler

Although the Swing component set provides alternatives to using pre-Swing AWT components (such as Button, List, and the like), one of the primary design goals for Swing was that it be based on AWT architecture. A significant benefit of such layering is that it greatly facilitates porting AWT-component programs to

Swing. In fact, because both the AWT and Swing component sets use the same AWT infrastructure, it's possible to mix both kinds of components in the same program -- a technique that allows for phased migration of applications. This article will lay out the rules for mixing components, and will provide some information and guidelines that we hope will make the mixing of AWT and Swing components as painless as possible.

NOTE: If you aren't familiar with AWT components or their architecture, see the "Introducing

Swing" article in the current issue.

Heavy and light components


Most of the issues related to mixing AWT and Swing components are related to the mixing of so-called heavyweight and lightweight components. A heavyweight component is one that is associated with its own native screen resource (commonly known as a peer). A lightweight component is one that "borrows" the screen resource of an ancestor (which means it has no native resource of its own -- so it's "lighter"). (Lightweight component support was introduced in JDK1.1, and you can read more about it in the JDK1.1 Lightweight UI Framework design document.) We generally don't recommend mixing Swing and AWT components because there are significant benefits in sticking with programs that are written entirely in Swing (and thus use only lightweight components). Some of the benefits of using Swing components are: More efficient use of resources: Lightweight components are really "lighter" than heavyweight components. More consistency across platforms because Swing is written entirely in Java. Cleaner look-and-feel integration: You can give a set of components a matching look-andfeel by implementing them using Swing. Despite the benefits of using Swing components exclusively, a developer may sometimes have to mix AWT components and Swing components in the same program (even when migration is not to blame). For example, such mixing may be required when a Swing version of a particular AWT component is not yet available. Because there's sometimes no alternative to mixing heavyweight and lightweight components, we have provided a few options in Swing to make a certain level of component-mixing possible. However, as anyone who has tried this approach knows, there are some practical limitations to this approach.

Heavy vs. light: the differences

There are some significant differences between lightweight and heavyweight components. And, since all AWT components are heavyweight and all Swing components are lightweight (except for the toplevel ones: JWindow, JFrame, JDialog, and JApplet), these differences become painfully apparent when you start mixing Swing components with AWT components. The differences boil down to the following: A lightweight component can have transparent pixels; a heavyweight is always opaque. A lightweight component can appear to be non-rectangular because of its ability to set transparent areas; a heavyweight can only be rectangular. Mouse events on a lightweight component fall through to its parent; mouse events on a heavyweight component do not fall through to its parent. When a lightweight component overlaps a heavyweight component, the heavyweight component is always on top, regardless of the relative z-order of the two components.

Z-order limitations
It is Issue No. 4 -- the one that applies to overlapping components -- that causes the most grief for developers who are mixing AWT and Swing components. This limitation exists because of the fact that a lightweight component re-uses the screen real estate of its nearest heavyweight ancestor and is therefore restricted to the z-order position of that ancestor. To illustrate, say your application had the following containment hierarchy (where "H" means heavyweight and "L" means lightweight):

For the sake of the example, let's assume that the two labels overlap, and that the z-order value of the Swing label places it "on top" of the AWT label. But it still looks like this:

The Swing label will never appear to be on top of the AWT label because the Swing label is rendering its contents in the native window of the frame (its first heavyweight ancestor), while the AWT label is rendering its contents in its own native window, which is actually a child of the frame's native window. If the Swing and AWT components do not overlap, then in general there should be no problems mixing them within the same container.

Guideline No. 1 Do not mix lightweight (Swing) and heavyweight (AWT) components within a container where the lightweight component is expected to overlap the heavyweight one.

Swing-specific Z-order issues


The lightweight/heavyweight z-order limitation causes some problems in specific areas of Swing. When developers run into these problems, they often don't realize the cause, and immediately conclude that there's a bug in Swing. The three most common z-order-related problems have to do with Swing's JScrollPane and JInternalFrame classes, and its popup components.

Swing's ScrollPane
Both the JScrollPane class and its viewport -- which clips its scrollable child -- are lightweight components. Consequently, heavyweight components cannot be handled properly when they are placed inside a JScrollPane's viewport. This is a window created by a little program that places both a Swing JButton and an AWT Button within a JScrollPane:

As you can see, the lightweight viewport cannot -- and does not -- clip the heavyweight AWT button properly.

Guideline No. 2

Do not place heavyweight (AWT) components inside a JScrollPane. If you need to scroll areas containing heavyweight components, use AWT's ScrollPane instead.

Swing's JInternalFrame component

Swing's JInternalFrame is a lightweight component. Typically, InternalFrame components are placed inside a JDesktopPane component, where the user can move the InternalFrames around in such a way that they can potentially overlap. Therefore, if heavyweight components are placed inside an InternalFrame, and that InternalFrame is overlapped by another InternalFrame, the first frame's heavyweight children will always be on top, potentially obscuring the other InternalFrame. This is a screen shot that illustrates this problem:

The Swing team is considering adding the option of creating InternalFrames as heavyweight containers in a future Swing release to alleviate this problem. However, until then, adhere to the following guideline:

Guideline No. 3

Do not place heavyweight (AWT) components inside a JInternalFrame.

Swing popup components

Swing provides a number of components that create popup windows (windows that dynamically appear when the user clicks on the component). These popup components are JPopupMenu, JComboBox, and JMenuBar. Swing attempts to maximize popup performance by dynamically choosing the most efficient container to display a popup just prior to showing the popup. The types of popups created are: LightWeight Popup: a lightweight container. MediumWeight Popup: an AWT heavyweight Panel. HeavyWeight Popup: a JWindow (heavyweight top-level window).

The rules that Swing uses to determine which popup to use are: If a popup does not fit within the bounds of the top-level window that contains the popup component, then a HeavyWeight popup is always used to ensure the entire popup will be visible. If a popup will fit within the bounds of the top-level window which contains the popup

component, and a popup's lightWeightPopupEnabled property is true, then a LightWeight popup is used for maximum efficiency. If a popup will fit within the bounds of the top-level window that contains the popup component, and a popup's lightWeightPopupEnabled property is false, then a MediumWeight popup is used. Another benefit of displaying lightweight and medium-weight popups is that within a browser environment, this strategy avoids the display of the "Warning Applet" banner in the menus. By default, the lightWeightPopupEnabled property is set to true for all popup components. Therefore, if you place a Swing popup component in a container that also contains an AWT heavyweight control, then it's possible that the popup will be obscured by the heavyweight control (if conditions are such that a "lightweight popup" is used). For example, if you place a JComboBox and an AWT Button in a panel, you might see the following result when you activate the combo box:

Notice that the combo box's popup window is painted behind the AWT button! Fortunately, programs can easily disable the LightWeight Popup feature by setting the lightWeightPopupEnabled property to false. There are two ways to perform this operation. First, you can change the default value for this property globally for a program using the following static method on JPopupMenu:

Once this method is invoked with a value of false, all popup components subsequently instantiated will initialize their lightWeightPopupEnabled property to false. Second, a program can control this for individual popup instances by using instance methods provided by JPopupMenu and JComboBox:

Setting this property on individual popup instances will override the default value controlled by the static JPopupMenu method.

Example: Mixing components


The following sample program mixes a Swing MenuBar (a lightweight component) with an AWT Button (A heavyweight component). The "Lite" menu-bar menu defaults to enable lightweight popups

while the "Heavy" menu uses the setDefaultLightWeightPopupEnabled() method to ensure the menu is never lightweight.

Guideline No. 4

If you place Swing popup components in a window containing heavyweight components and it's possible that the popup windows will intersect a heavyweight, then invoke

before the popup components are instantiated.

Summary
If you understand the limitations of mixing Swing and AWT components, it is generally possible to build Java programs which use both in harmony. However, because there are significant advantages to using lightweight components, we recommend using lightweights (and Swing!) wherever possible and only using heavyweight components where a lightweight version either isn't yet available or doesn't meet your program's needs.

You might also like