In Part I of this short course you will:
- Find out about the need for
JavaTM Foundation Classes (JFC)-Swing
and its advantages over the Abstract Window Toolkit (AWT)
- Learn about the JFC-Swing Controls
- Learn about the JFC-Swing Layout Managers
Course Outline
Sun Microsystems is leveraging the technology of
NetscapeTM Communications, IBM, and
Lighthouse Design (now owned by Sun) to create a set of Graphical
User Interface (GUI) classes that integrate with
JDKTM 1.1.5+, are standard with the Java
® 2 platform and provide a more polished
look and feel than the standard AWT component set. The collection of APIs
coming out of this effort, called the Java Foundation Classes (JFC), allows
developers to build full-featured enterprise-ready applications.
JFC is composed of five APIs: AWT, JavaTM
2D, Accessibility, Drag and Drop, and Swing. The AWT components refer to the
AWT as it exists in JDK versions 1.1.2 and later. Java 2D is a graphics API
based on technology licensed from IBM/Taligent. It is currently available
with the Java® 2 Platform (and not usable with JDK 1.1). The Accessibility
API provides assistive technologies, like screen magnifiers, for use with
the various pieces of JFC. Drag and Drop support is part of the next
JavaBeanTM generation, "Glasgow,"
and is also available with the Java® 2 platform.
Swing includes a component set that is targeted at forms-based applications.
Loosely based on Netscape's acclaimed Internet Foundation Classes (IFC), the
Swing components have had the most immediate impact on Java development. They
provide a set of well-groomed widgets and a framework to specify how GUIs are
visually presented, independent of platform. At the time this was written, the
Swing release is at 1.1 (FCS).
Though the Swing widgets were based heavily on IFC, the two APIs bear
little resemblance to one another from the perspective of a developer.
The look and feel of some Swing widgets and their rendering is primarily
what descended from IFC, although you may notice some other commonalties.
The AWT 1.1 widgets and event model are still present for the Swing widgets.
However, the 1.0 event model does not work with Swing widgets. The Swing
widgets simply extend AWT by adding a new set of components, the
JComponents, and a group of related support classes. As with
AWT, Swing components are all JavaBeans and participate in the JavaBeans
event model.
A subset of Swing widgets is analogous to the basic AWT widgets. In some
cases, the Swing versions are simply lightweight components, rather than
peer-based components. The lightweight component architecture was introduced
in AWT 1.1. It allows components to exist without native operating
system widgets. Instead, they participate in the Model/View/Controller
(MVC) architecture, which will be described in Part II of this course. Swing
also contains some new widgets such as trees, tabbed panes, and splitter
panes that will greatly improve the look and functionality of GUIs.
Swing can expand and simplify your development of cross-platform applications.
The Swing collection consists of seventeen packages, each of which has its own
distinct purpose. As you'll learn in this short course, these packages make it
relatively easy for you to put together a variety of applications that have a
high degree of sophistication and user friendliness.
javax.swing
- The high level swing package primarily consists of components,
adapters, default component models, and interfaces for all the
delegates and models.
javax.swing.border
- The border package declares the
Border
interface and
classes, which define specific border rendering styles.
javax.swing.colorchooser
- The colorchooser package contains support classes for the color
chooser component.
javax.swing.event
- The event package is for the Swing-specific event types and
listeners. In addition to the
java.awt.event
types, Swing
components can generate their own event types.
javax.swing.filechooser
- The filechooser package contains support classes for the file
chooser component.
javax.swing.plaf.*
- The pluggable look-and-feel (PLAF) packages contain the User
Interface (UI) classes (delegates) which implement the different
look-and-feel aspects for Swing components. There are also PLAF
packages under the
javax.swing.plaf
hierarchy.
javax.swing.table
- The table package contains the support interfaces and classes
the Swing table component.
javax.swing.text
- The text package contains the support classes for the Swing
document framework.
javax.swing.text.html.*
- The text.html package contains the support classes for an
HTML version 3.2 renderer and parser.
javax.swing.text.rtf
- The text.rtf package contains the support classes for a basic
Rich Text Format (RTF) renderer.
javax.swing.tree
- The tree package contains the interfaces and classes which
support the Swing tree component.
javax.swing.undo
- The undo package provides the support classes for implementing
undo/redo capabilities in a GUI.
javax.accessibility
- The JFC Accessibility package is included with the Swing classes.
However, its usage is not discussed here.
This section describes how to use the various Swing widgets. The Swing
component hierarchy is shown in two parts for comparison with AWT. Part
1 of the component hierarchy is similar to that of AWT.
However, there
are over twice as many components in Swing as in AWT. Part 2 shows the
expanded Swing component set. This group of components appeals most to
developers, as it provides a much richer set of widgets to use.
Component Hierarchy: Part 1--AWT Similar
Component Hierarchy: Part 2--New And Expanded Components
The first widget to discuss is JPanel
. It is a lightweight
Panel
object offering built-in support for double buffering. When
buffering is enabled, through the constructor, all the drawing operations
of components within the panel will be drawn to an off-screen drawing area
prior to being drawn to the screen. The JPanel
class is used in
most of the examples in this section.
The second component, Icon
, isn't really a component at all.
However, you can use it with almost all Swing components.
An Icon
is used to describe fixed-size pictures, or
glyphs. Typically, you embed icons in a JButton
or other
JComponent
. Objects that can act as icons implement the
Icon
interface, shown below. It contains a
paintIcon()
method that specifies a drawing origin. You
render the picture specified in the paintIcon()
method
in a rectangle whose size cannot exceed a rectangle with an origin at
(x
, y
), a width of getIconWidth()
,
and a height of getIconHeight()
. The Component
parameter to paintIcon()
is not usually used, unless you
need to specify additional information, such as a font or color.
public interface Icon {
void paintIcon(
Component c, Graphics g, int x, int y);
int getIconWidth();
int getIconHeight();
}
The ImageIcon
class is an implementation of Icon
that
creates an Icon
from an Image
.
Icon tinyPicture = new ImageIcon("TinyPicture.gif");
Alternatively, the ImageIcon
constructor can take an Image
or URL
object or byte array as its parameter, with an optional
String
description parameter. One nice thing about ImageIcon
is it checks a cache before retrieving the image file.
Swing uses ImageIcon
rather than Image
for two reasons:
- An
Image
loads asynchronously, creating the
need to monitor the loading process (with MediaTracker
).
- An
Image
is not serializable.
In addition to using ImageIcon
, you can implement the interface yourself
to create your own icons:
public class RedOval implements Icon {
public void paintIcon (Component c, Graphics g,
int x, int y) {
g.setColor(Color.red);
g.drawOval (x, y, getIconWidth(), getIconHeight());
}
public int getIconWidth() {
return 10;
}
public int getIconHeight() {
return 10;
}
}
A JLabel
is a single line label similar to java.awt.Label
.
Additional functionality that a JLabel
has is the ability to:
- Add an
Icon
- Set the vertical and horizontal position of text
relative to the
Icon
- Set the relative position of contents within component
public class LabelPanel extends JPanel {
public LabelPanel() {
// Create and add a JLabel
JLabel plainLabel = new JLabel("Plain Small Label");
add(plainLabel);
// Create a 2nd JLabel
JLabel fancyLabel = new JLabel("Fancy Big Label");
// Instantiate a Font object to use for the label
Font fancyFont =
new Font("Serif", Font.BOLD | Font.ITALIC, 32);
// Associate the font with the label
fancyLabel.setFont(fancyFont);
// Create an Icon
Icon tigerIcon = new ImageIcon("SmallTiger.gif");
// Place the Icon in the label
fancyLabel.setIcon(tigerIcon);
// Align the text to the right of the Icon
fancyLabel.setHorizontalAlignment(JLabel.RIGHT);
// Add to panel
add(fancyLabel);
}
}
A JButton
can be instantiated and used in a GUI just like a
java.awt.Button
. It behaves like an AWT 1.1 Button
,
notifying ActionListener
list elements when pushed.
public class ButtonPanel extends JPanel {
public ButtonPanel () {
JButton myButton = new JButton("Tiger");
add(myButton);
}
}
Also, the JButton
has support for an embedded Icon
,
specified in the constructor, or via the setIcon()
method. This
creates an image button; here, with the label Tiger:
public class ButtonPanel extends JPanel {
public ButtonPanel() {
Icon tigerIcon = new ImageIcon("SmallTiger.gif");
JButton myButton = new JButton("Tiger", tigerIcon);
add(myButton);
}
}
Magercises
- Installing Swing and
SwingSet Demonstration
- Creating Your First
JFC Application
- Creating Buttons With Icons
While the AbstractButton
isn't a class you use directly,
several of the more common JComponent
classes inherit much
of their shared behavior from this object. For instance, the icon usage
methods getIcon()
and setIcon()
come from
AbstractButton
. (The methods are also available elsewhere.)
Some of the other common features are listed below:
setMnemonic()
- Add a keyboard accelerator to a text label,
use the VK_*
constants from KeyEvent
to specify
the key
doClick()
- Programmatically, select the button
setDisabledIcon()
, setDisabledSelectedIcon()
,
setPressedIcon()
, setRolloverIcon()
,
setRolloverSelectedIcon()
, setSelectedIcon()
-
Change the displayed Icon
, based on the button state (in
addition to setIcon()
)
setVerticalAlignment()
,
setHorizontalAlignemnt()
-
Anchors icon/text in different areas of button
setVerticalTextPosition()
,
setHorizontalTextPosition()
- Positions text in different areas around icon. Both
setXXXAlignment()
and
setYYYTextPosition()
rely on the
SwingConstants
interface for the area placement settings.
Note: The upcoming Swing 1.1.1
release
includes the ability to specify label text in HTML by
preceding the content with <html>. This
will allow
you to have multi-line button labels without having
to
customize the user interface.
A JCheckBox
is similar to an AWT Checkbox
that
is not in a CheckboxGroup
. Although Swing provides a default
graphic to signify JCheckBox
selection, you also can specify
your own Icon
objects for both the checked and unchecked state.
public class CheckboxPanel extends JPanel {
Icon unchecked = new ToggleIcon (false);
Icon checked = new ToggleIcon (true);
public CheckboxPanel() {
// Set the layout for the JPanel
setLayout(new GridLayout(2, 1));
// Create checkbox with its state
// initialized to true
JCheckBox cb1 = new JCheckBox("Choose Me", true);
cb1.setIcon(unchecked);
cb1.setSelectedIcon(checked);
// Create checkbox with its state
// initialized to false
JCheckBox cb2 = new JCheckBox(
"No Choose Me", false);
cb2.setIcon(unchecked);
cb2.setSelectedIcon(checked);
add(cb1);
add(cb2);
}
class ToggleIcon implements Icon {
boolean state;
public ToggleIcon (boolean s) {
state = s;
}
public void paintIcon (Component c, Graphics g,
int x, int y) {
int width = getIconWidth();
int height = getIconHeight();
g.setColor (Color.black);
if (state)
g.fillRect (x, y, width, height);
else
g.drawRect (x, y, width, height);
}
public int getIconWidth() {
return 10;
}
public int getIconHeight() {
return 10;
}
}
}
In AWT, radio buttons are checkboxes that belong to the same
CheckboxGroup
; which ensures that only one checkbox
is selected at a time. Swing has a separate widget called a
JRadioButton
. Each JRadioButton
is added to a
ButtonGroup
so the group behaves as a set of radio buttons.
Like CheckboxGroup
, ButtonGroup
is a functional
object that has no visual representation.
public class RadioButtonPanel extends JPanel {
public RadioButtonPanel() {
// Set the layout to a GridLayout
setLayout(new GridLayout(4,1));
// Declare a radio button
JRadioButton radioButton;
// Instantiate a ButtonGroup for functional
// association among radio buttons
ButtonGroup rbg = new ButtonGroup();
// Create a label for the group
JLabel label = new JLabel("Annual Salary: ");
label.setFont(new Font(
"SansSerif", Font.BOLD, 14));
add(label);
// Add a new radio button to the pane
radioButton = new JRadioButton("$45,000");
add (radioButton);
// set key accelerator
radioButton.setMnemonic (KeyEvent.VK_4);
// Add the button to the ButtonGroup
rbg.add (radioButton);
// Set this radio button to be the default
radioButton.setSelected(true);
// Set up two more radio buttons
radioButton = new JRadioButton("$60,000");
radioButton.setMnemonic (KeyEvent.VK_6);
add (radioButton);
rbg.add (radioButton);
radioButton = new JRadioButton("$75,000");
radioButton.setMnemonic (KeyEvent.VK_7);
add (radioButton);
rbg.add (radioButton);
}
}
Technically speaking, you can add JCheckBox
or JToggleButton
(described next) components to a CheckboxGroup
. At most, one
will be selected while in the group.
The JToggleButton
class is the parent to both
JCheckBox
and JRadioButton
. It doesn't have an AWT
equivalent. The JToggleButton
works like a Button
that stays pressed in when toggled on. When a JToggleButton
is
toggled off, you cannot tell it from a regular Button
or
JButton
class.
public class ToggleButtonPanel extends JPanel {
public ToggleButtonPanel() {
// Set the layout to a GridLayout
setLayout(new GridLayout(4,1, 10, 10));
add (new JToggleButton ("Fe"));
add (new JToggleButton ("Fi"));
add (new JToggleButton ("Fo"));
add (new JToggleButton ("Fum"));
}
}
Like the AWT 1.1 ScrollPane
, JScrollPane
handles
automatic horizontal and vertical scrolling of content. It lays out components
using a ScrollPaneLayout
, described in more detail under
Swing Layouts. The key thing to know when using a
JScrollPane
is that Swing provides a JViewport
for adding the object to scroll.
To get a handle to the viewport, JScrollPane
has a
getViewport()
method. Then, to add a component to the viewport,
the JViewport
class has an add
method.
JViewport vport = someScrollPane.getViewport();
vport.add(someComponent);
Or, more commonly, the two lines are combined:
someScrollPane.getViewport().add(someComponent);
Another option is to provide the component to scroll to the constructor:
JScrollPane pane = new JScrollPane(someComponent);
public class ScrollPanel extends JPanel {
public ScrollPanel() {
setLayout(new BorderLayout());
Icon bigTiger = new ImageIcon("BigTiger.gif");
JLabel tigerLabel = new JLabel(bigTiger);
JScrollPane scrollPane =
new JScrollPane(tigerLabel);
add(scrollPane, BorderLayout.CENTER);
}
}
The JViewport
offers a view into a much larger area then can be
seen without it. It can be either used within the JScrollPane
component or as a standalone widget, where you control all the scrolling
functionality yourself. Normally, you wouldn't want to do all the scrolling
functionality yourself, but the capability is available. (Besides
JScrollPane
, JViewport
is used internally within
the Swing text components to
handle scrolling of text.)
Magercise
- Using Toggles
JTextComponent
is a generalized text class that contains all
the features you would expect from a simple editor. Some of its methods
include:
copy()
cut()
paste()
getSelectedText()
setSelectionStart()
setSelectionEnd()
selectAll()
replaceSelection()
getText()
setText()
setEditable()
setCaretPosition()
Although you won't instantiate a JTextComponent
object directly,
you will often use these methods, many of which are not available in AWT
text widgets.
JTextComponent
objects in Swing can be placed in a panel in a
fashion nearly identical to AWT text widgets.
There are three basic subclasses of JTextComponent
:
JTextField
, JTextArea
, and JEditorPane
.
JPasswordField
and JTextPane
are sub-subclasses
that are also of interest.
If you want your users to be able to see content that exceeds
the screen display area, you must place the component inside
of a JScrollPane
to support scrolling to the extra
content.
Other than having to add a JTextArea
to a JScrollPane
for scrolling, JTextField
and JTextArea
behave very
similarly to their AWT counterparts: java.awt.TextField
and
java.awt.TextArea
:
// Instantiate a new TextField
JTextField tf = new JTextField();
// Instantiate a new TextArea
JTextArea ta = new JTextArea();
// Initialize the text of each
tf.setText("TextField");
ta.setText("JTextArea\n Allows Multiple Lines");
add(tf);
add(new JScrollPane(ta));
The JTextField
also supports setting of text justification
with setHorizontalAlignment()
. The three available settings
are
LEFT
, CENTER
, and RIGHT
, where
LEFT
is the default.
JTextPane
is a full-featured text editor that supports
formatted text, word wrap, and image display. It uses a linked list
of objects that implement the Style
interface to specify
formatting and supplies some convenience methods for formatting text.
A more detailed discussion of JTextPane
usage, and the
javax.swing.text
package, is included in Part II of this
course.
JTextPane tp = new JTextPane();
MutableAttributeSet attr = new SimpleAttributeSet();
StyleConstants.setFontFamily(attr, "Serif");
StyleConstants.setFontSize(attr, 18);
StyleConstants.setBold(attr, true);
tp.setCharacterAttributes(attr, false);
add(new JScrollPane(tp));
public class TextPanel extends JPanel {
public TextPanel() {
// Set the layout to a BorderLayout
setLayout(new BorderLayout());
// Create the three basic text components
JTextField textField = new JTextField();
JTextArea textArea = new JTextArea();
JTextPane textPane = new JTextPane();
//Set the textpane's font properties
MutableAttributeSet attr =
new SimpleAttributeSet();
StyleConstants.setFontFamily(attr, "Serif");
StyleConstants.setFontSize(attr, 18);
StyleConstants.setBold(attr, true);
textPane.setCharacterAttributes(attr, false);
add(textField, BorderLayout.NORTH);
add(new JScrollPane(textArea),
BorderLayout.CENTER);
add(new JScrollPane(textPane), BorderLayout.SOUTH);
}
}
The JPasswordField
is a JTextField
that refuses to
display its contents openly. By default, the mask character is the asterisk
('*'). However, you can change this with the setEchoChar()
method. Unlike java.awt.TextField
, an echo character of
(char)0
does not unset the mask.
class PasswordPanel extends JPanel {
PasswordPanel() {
JPasswordField pass1 = new JPasswordField(20);
JPasswordField pass2 = new JPasswordField(20);
pass2.setEchoChar ('?');
add(pass1);
add(pass2);
}
}
The JEditorPane
class is a specialized JTextComponent
for displaying and editing HTML 3.2 tags or some other format like RTF (rich
text format), as determined by the input. It is not meant to provide a
full-fledged browser, but a lightweight HTML viewer, usually for the purpose
of displaying help text. You either construct the pane with a URL parameter
(via a String
or URL
), or change pages with the
setPage()
method. For HTML content, links within the HTML page
are traversable with the help of a HyperlinkListener
.
public class Browser extends JPanel {
Browser() {
setLayout (new BorderLayout (5, 5));
final JEditorPane jt = new JEditorPane();
final JTextField input =
new JTextField("http://java.sun.com");
// make read-only
jt.setEditable(false);
// follow links
jt.addHyperlinkListener(new HyperlinkListener () {
public void hyperlinkUpdate(
final HyperlinkEvent e) {
if (e.getEventType() ==
HyperlinkEvent.EventType.ACTIVATED) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Save original
Document doc = jt.getDocument();
try {
URL url = e.getURL();
jt.setPage(url);
input.setText (url.toString());
} catch (IOException io) {
JOptionPane.showMessageDialog (
Browser.this, "Can't follow link",
"Invalid Input",
JOptionPane.ERROR_MESSAGE);
jt.setDocument (doc);
}
}
});
}
}
});
JScrollPane pane = new JScrollPane();
pane.setBorder (
BorderFactory.createLoweredBevelBorder());
pane.getViewport().add(jt);
add(pane, BorderLayout.CENTER);
input.addActionListener (new ActionListener() {
public void actionPerformed (ActionEvent e) {
try {
jt.setPage (input.getText());
} catch (IOException ex) {
JOptionPane.showMessageDialog (
Browser.this, "Invalid URL",
"Invalid Input",
JOptionPane.ERROR_MESSAGE);
}
}
});
add (input, BorderLayout.SOUTH);
}
}
To activate the hyperlinks within the JEditorPane
, event handling
code is provided. Also, if you only want to display HTML, remember to
setEditable(false)
to make the editor read-only.
JScrollBar
offers a lightweight version of the
java.awt.Scrollbar
component.
public class ScrollbarPanel extends JPanel {
public ScrollbarPanel() {
setLayout(new BorderLayout());
JScrollBar scrollBar1 = new JScrollBar (
JScrollBar.VERTICAL, 0, 5, 0, 100);
add(scrollBar1, BorderLayout.EAST);
JScrollBar scrollBar2 = new JScrollBar (
JScrollBar.HORIZONTAL, 0, 5, 0, 100);
add(scrollBar2, BorderLayout.SOUTH);
}
}
JSlider
functions like a JScrollBar
; however, it adds the
ability to display major and minor tick marks, as well as display a
Border
around the slider.
public class SliderPanel extends JPanel {
public SliderPanel() {
setLayout(new BorderLayout());
JSlider slider1 =
new JSlider (JSlider.VERTICAL, 0, 100, 50);
slider1.setPaintTicks(true);
slider1.setMajorTickSpacing(10);
slider1.setMinorTickSpacing(2);
add(slider1, BorderLayout.EAST);
JSlider slider2 =
new JSlider (JSlider.VERTICAL, 0, 100, 50);
slider2.setPaintTicks(true);
slider2.setMinorTickSpacing(5);
add(slider2, BorderLayout.WEST);
JSlider slider3 =
new JSlider (JSlider.HORIZONTAL, 0, 100, 50);
slider3.setPaintTicks(true);
slider3.setMajorTickSpacing(10);
add(slider3, BorderLayout.SOUTH);
JSlider slider4 =
new JSlider (JSlider.HORIZONTAL, 0, 100, 50);
slider4.setBorder(
BorderFactory.createLineBorder(Color.blue));
add(slider4, BorderLayout.NORTH);
}
}
In addition to plain tick marks, with JSlider
you can place
labels along the axis as either a serious of numbers or components.
For numeric labels, by just calling setPaintLabels (true)
,
the slider will generate and use a series of labels based on the major
tick spacing. So, if the slider range is 0 to 100 with tick spacing of
10, the slider would then have labels of 0, 10, 20, ... 100. On the
other hand, if you want to generate the labels yourself, you can provide
a Hashtable
of labels. The hashtable key would be the
Integer
value of the position. The hashtable value would be a
Component
to use for display of the label. The following
demonstrates both:
public class SliderPanel2 extends JPanel {
public SliderPanel2() {
setLayout(new BorderLayout());
JSlider right, bottom;
right = new JSlider(JSlider.VERTICAL, 1, 9, 3);
Hashtable h = new Hashtable();
h.put (new Integer (1), new JLabel("Mercury"));
h.put (new Integer (2), new JLabel("Venus"));
h.put (new Integer (3), new JLabel("Earth"));
h.put (new Integer (4), new JLabel("Mars"));
h.put (new Integer (5), new JLabel("Jupiter"));
h.put (new Integer (6), new JLabel("Saturn"));
h.put (new Integer (7), new JLabel("Uranus"));
h.put (new Integer (8), new JLabel("Neptune"));
h.put (new Integer (9), new JLabel("Pluto"));
right.setLabelTable (h);
right.setPaintLabels (true);
right.setInverted (true);
bottom =
new JSlider(JSlider.HORIZONTAL, 0, 100, 25);
bottom.setMajorTickSpacing (10);
bottom.setPaintLabels (true);
add(right, BorderLayout.EAST);
add(bottom, BorderLayout.SOUTH);
}
}
The JProgressBar
component allows you to display a progress bar
to reflect the status of an operation. The general format of using a
JProgressBar
is as follows:
- Initialize the
JProgressBar
:
JProgressBar progressBar = new JProgressBar();
progressBar.setMinimum(0);
progressBar.setMaximum(numberSubOperations);
- Repeat each time you want to perform an operation:
progressBar.setValue(progressBar.getMinimum());
for (int i = 0; i < numberSubOperations; i++) {
// Perform sub-operation i
// Update bar value in event thread
// Where runner is created outside for loop
SwingUtilities.invokeAndWait(runner);
}
- Outside the for-loop, create the
Runnable
object
Runnable runner = new Runnable() {
public void run() {
int value = progressBar.getValue();
progressBar.setValue(value+1);
}
};
Often, you will want to set up an operation to execute in a thread and have
the operation monitored by a progress bar. This allows the user to cancel the
operation if it is taking too long. (The ProgressMonitorInputStream
class provides this type of behavior for reading input streams.)
To demonstrate JProgressBar
, an example follows. The stepping thread
simply counts up, displaying the current count in a JTextField
. In
addition, the bar displays the current value by setting its stringPainted
property to true
with progressBar.setStringPainted(true)
.
public class ProgressBarPanel extends JPanel {
Thread loadThread;
Object lock = new Object();
boolean shouldStop=false;
JTextField progressTextField;
JProgressBar progressBar;
public ProgressBarPanel() {
setLayout(new BorderLayout());
progressTextField = new JTextField();
add(progressTextField, BorderLayout.NORTH);
JPanel bottomPanel = new JPanel();
progressBar = new JProgressBar();
progressBar.setStringPainted(true);
bottomPanel.setLayout(new GridLayout(0,1));
bottomPanel.add(progressBar);
bottomPanel.add(new JLabel("Load Status"));
JPanel buttonPanel = new JPanel();
JButton startButton = new JButton("Start");
buttonPanel.add(startButton);
startButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
startLoading();
}
});
JButton stopButton = new JButton("Stop");
buttonPanel.add(stopButton);
stopButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
stopLoading();
}
});
bottomPanel.add(buttonPanel);
add(bottomPanel, BorderLayout.SOUTH);
}
public void startLoading() {
if(loadThread == null) {
loadThread = new LoadThread();
shouldStop = false;
loadThread.start();
}
}
public void stopLoading() {
synchronized(lock) {
shouldStop = true;
lock.notify();
}
}
class LoadThread extends Thread {
public void run () {
int min = 0;
int max = 100;
progressBar.setValue(min);
progressBar.setMinimum(min);
progressBar.setMaximum(max);
Runnable runner = new Runnable() {
public void run() {
int value = progressBar.getValue();
value++;
progressBar.setValue(value);
progressTextField.setText (""+value);
}
};
for (int i=min;i<=max;i++) {
try {
SwingUtilities.invokeAndWait(runner);
} catch (InvocationTargetException e) {
break;
} catch (InterruptedException e) {
// Ignore Exception
}
synchronized(lock) {
if(shouldStop)
break;
try {
lock.wait(100);
} catch (InterruptedException e) {
// Ignore Exception
}
}
}
loadThread = null;
}
}
}
The JComboBox
works like AWT's Choice
component, but
renames some methods and offers an editable option. For times when a fixed-list
of choices isn't enough, you can offer a JComboBox
with a list of
default choices, but still permit the entry of another value. The nicest part
about this control is that when the user presses the key for the first letter
of an entry, it changes the highlighted selection. You can enhance this
behavior by providing your own KeySelectionManager
, a public
inner class of JComboBox
.
public class ComboPanel extends JPanel {
String choices[] = {
"Mercury", "Venus", "Earth",
"Mars", "Jupiter", "Saturn",
"Uranus","Neptune", "Pluto"};
public ComboPanel() {
JComboBox combo1 = new JComboBox();
JComboBox combo2 = new JComboBox();
for (int i=0;i<choices.length;i++) {
combo1.addItem (choices[i]);
combo2.addItem (choices[i]);
}
combo2.setEditable(true);
combo2.setSelectedItem("X");
combo2.setMaximumRowCount(4);
add(combo1);
add(combo2);
}
}
There is more to JComboBox
than just a few new methods and
editability. Details are included in Part II of this course, after the
Model/View/Controller (MVC) Architecture has been explained.
The JList
component has both an easy (non-MVC) implementation and
a more complicated view. For the MVC-view, you'll see an example in Part II of
this course with JComboBox
. For now, you'll see how to display a
list of String
objects, just like an AWT List
component. Thankfully, it has gotten much easier. To add a
String[]
(or Vector
) of elements
to a JList
, just tell the constructor or use
the setListData()
method.
There is one major difference between List
and JList
.
JList
doesn't directly support scrolling. You need to place the
JList
within a JScrollPane
object, and let it deal with
the scrolling.
public class ListPanel extends JPanel {
String label [] = {"Cranberry", "Orange",
"Banana", "Kiwi", "Blueberry",
"Pomegranate", "Apple", "Pear",
"Watermelon", "Raspberry", "Snozberry"
};
public ListPanel() {
setLayout (new BorderLayout());
JList list = new JList(label);
JScrollPane pane = new JScrollPane(list);
add(pane, BorderLayout.CENTER);
}
}
The javax.swing.border
package consists of several objects to
draw borders around components. They all implement the Border
interface, which consists of three methods:
public Insets getBorderInsets(Component c)
Defines the drawable area necessary to draw the border
public boolean isBorderOpaque()
Defines if the border area is opaque or transparent
public void paintBorder (Component c, Graphics g, int x,
int y, int width, int height)
Defines how to draw the border within the specified area.
The routine should only draw into the area requested with
getBorderInsets()
.
The border behavior is defined for JComponent
, so all subclasses
inherit the behavior.
Swing provides nine borders, and you can create your own if none of them meets
your needs:
AbstractBorder
- An abstract class that implements the
Border
interface, but does nothing
BevelBorder
- A 3D border that may be raised or lowered
CompoundBorder
- A border that can nest multiple borders
EmptyBorder
- A border where you specify the
reserved space for an undrawn border
EtchedBorder
- A border that appears as a groove, instead
of raised or lowered
LineBorder
- A border for single color borders, with
arbitrary thickness
MatteBorder
- A border that permits tiling of an icon
or color
SoftBevelBorder
- A 3D border with softened corners
TitledBorder
- A border that permits title strings in
arbitrary locations
You can create a border object directly from the appropriate class constructor
or ask a BorderFactory
to create the border for you, with methods
like createBevelBorder(type)
and
createTitledBorder("TItle")
. When using BorderFactory
,
multiple requests to create the same border return the same object.
public class BorderPanel extends JPanel {
class MyBorder implements Border {
Color color;
public MyBorder (Color c) {
color = c;
}
public void paintBorder (Component c, Graphics g,
int x, int y, int width, int height) {
Insets insets = getBorderInsets(c);
g.setColor (color);
g.fillRect (x, y, 2, height);
g.fillRect (x, y, width, 2);
g.setColor (color.darker());
g.fillRect (x+width-insets.right, y, 2, height);
g.fillRect (x, y+height-insets.bottom, width, 2);
}
public boolean isBorderOpaque() {
return false;
}
public Insets getBorderInsets(Component c) {
return new Insets (2, 2, 2, 2);
}
}
public BorderPanel() {
setLayout (new GridLayout (4, 3, 5, 5));
JButton b = new JButton("Empty");
b.setBorder (new EmptyBorder (1,1,1,1));
add(b);
b = new JButton ("Etched");
b.setBorder (new EtchedBorder ());
add(b);
b = new JButton ("ColorizedEtched");
b.setBorder (new EtchedBorder (Color.red,
Color.green));
add(b);
b = new JButton ("Titled/Line");
b.setBorder(new TitledBorder (
new TitledBorder(
LineBorder.createGrayLineBorder(),
"Hello"),
"World",
TitledBorder.RIGHT,
TitledBorder.BOTTOM));
add(b);
b = new JButton ("Bevel Up");
b.setBorder(new BevelBorder(BevelBorder.RAISED));
add(b);
b = new JButton ("Bevel Down");
b.setBorder(new BevelBorder(BevelBorder.LOWERED));
add(b);
b = new JButton ("Soft Bevel Up");
b.setBorder(
new SoftBevelBorder(SoftBevelBorder.RAISED));
add(b);
b = new JButton ("Soft Bevel Down");
b.setBorder(
new SoftBevelBorder(SoftBevelBorder.LOWERED));
add(b);
b = new JButton ("Matte");
b.setBorder(
new MatteBorder(5, 10, 5, 10, Color.red));
add(b);
b = new JButton ("Matte Icon");
Icon icon = new ImageIcon ("SmallTiger.gif");
b.setBorder(new MatteBorder(10, 10, 10, 10, icon));
add(b);
b = new JButton ("ColorizedBezel");
b.setBorder(new BevelBorder(BevelBorder.RAISED,
Color.red, Color.pink));
add(b);
b = new JButton ("My/Compound");
b.setBorder(new CompoundBorder(
new MyBorder(Color.red),
new CompoundBorder (new MyBorder(Color.green),
new MyBorder(Color.blue))));
add(b);
}
}
You can change the border of any JComponent
object with the
setBorder()
method.
Magercise
- Using Borders
The menuing model used in Swing is nearly identical to that used in AWT.
There are three key exceptions:
- The menu classes (
JMenuItem
, JCheckBoxMenuItem
,
JMenu
, and JMenuBar
) are all subclasses of
JComponent
. They are not off in their own independent
class hierarchy. As a result of this, you can place a
JMenuBar
within any Container
, including
Applet
. [The JApplet
class has a
setJMenuBar()
method to add a JMenuBar
.]
- There is a new menu class,
JRadioButtonMenuItem
, to
provide a set of mutually exclusive checkboxes on a menu, when placed
within a ButtonGroup
.
- Also, you can associate an
Icon
object with any
JMenuItem
.
public class MenuTester extends JFrame
implements ActionListener {
public void actionPerformed (ActionEvent e) {
System.out.println (e.getActionCommand());
}
public MenuTester() {
super ("Menu Example");
JMenuBar jmb = new JMenuBar();
JMenu file = new JMenu ("File");
JMenuItem item;
file.add (item = new JMenuItem ("New"));
item.addActionListener (this);
file.add (item = new JMenuItem ("Open"));
item.addActionListener (this);
file.addSeparator();
file.add (item = new JMenuItem ("Close"));
item.addActionListener (this);
jmb.add (file);
JMenu edit = new JMenu ("Edit");
edit.add (item = new JMenuItem ("Copy"));
item.addActionListener (this);
Icon tigerIcon = new ImageIcon("SmallTiger.gif");
edit.add (item =
new JMenuItem ("Woods", tigerIcon));
item.setHorizontalTextPosition (JMenuItem.LEFT);
item.addActionListener (this);
edit.add (item =
new JMenuItem ("Woods", tigerIcon));
item.addActionListener (this);
jmb.add (edit);
JMenu choice = new JMenu ("Choices");
JCheckBoxMenuItem check =
new JCheckBoxMenuItem ("Toggle");
check.addActionListener (this);
choice.add (check);
ButtonGroup rbg = new ButtonGroup();
JRadioButtonMenuItem rad =
new JRadioButtonMenuItem ("Choice 1");
choice.add (rad);
rbg.add (rad);
rad.addActionListener (this);
rad = new JRadioButtonMenuItem ("Choice 2");
choice.add (rad);
rbg.add (rad);
rad.addActionListener (this);
rad = new JRadioButtonMenuItem ("Choice 3");
choice.add (rad);
rbg.add (rad);
rad.addActionListener (this);
jmb.add (choice);
setJMenuBar (jmb);
}
}
The JSeparator
object is the menu separator control. The image
below shows the separator under the File menu from the example above.
Because Swing menu objects are truly components, you can use
JSeparator
outside of menus, too. However, normally you just
add them to a JMenu
with addSeparator()
.
The JPopupMenu
component allows you to associate
context-sensitive menus with any JComponent
. They
work similarly to the AWT PopupMenu
class, with an
addSeparator()
method to add a separator bar.
public class PopupPanel extends JPanel {
JPopupMenu popup = new JPopupMenu ();
public PopupPanel() {
JMenuItem item;
popup.add (item = new JMenuItem ("Cut"));
popup.add (item = new JMenuItem ("Copy"));
popup.add (item = new JMenuItem ("Paste"));
popup.addSeparator();
popup.add (item = new JMenuItem ("Select All"));
popup.setInvoker (this);
addMouseListener (new MouseAdapter() {
public void mousePressed (MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show (e.getComponent(),
e.getX(), e.getY());
}
}
public void mouseReleased (MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show (e.getComponent(),
e.getX(), e.getY());
}
}
});
}
}
The Window
class hierarchy is a little different when the
Swing window classes are added.
As the diagram shows, they all subclass Window
, not
JComponent
. This means they are not lightweight,
have a peer, and cannot be transparent.
The JFrame
class is the replacement for AWT's Frame
class. In addition to the ability to add a java.awt.MenuBar
via
setMenuBar()
, you can add a JMenuBar
to a
JFrame
via setJMenuBar()
.
The other difference of the JFrame
class is shared with the
JWindow
and JDialog
classes. No longer do you just
add()
components to each directly or setLayout()
to change the LayoutManager
. Now, you must get what's called a
content pane, then add components to that or change its layout.
public class FrameTester {
public static void main (String args[]) {
JFrame f = new JFrame ("JFrame Example");
Container c = f.getContentPane();
c.setLayout (new FlowLayout());
for (int i = 0; i < 5; i++) {
c.add (new JButton ("No"));
c.add (new Button ("Batter"));
}
c.add (new JLabel ("Swing"));
f.setSize (300, 200);
f.show();
}
}
The reason you have to get a content pane is because the inside of a window
is now composed of a JRootPane
, which no longer shields you
from the inner workings of the Window
, as AWT did.
One other difference between JFrame
and Frame
is
JFrame
has a property that defines the default close operation.
With Frame
, nothing happens, by default, if you try to close
the frame. On the other hand, JFrame
will hide itself when you
try to close it. The setDefaultCloseOperation()
method lets you
define three operations that can happen when the user tries to close a
JFrame
:
DO_NOTHING_ON_CLOSE
: The AWT Frame
behavior
HIDE_ON_CLOSE
: The default behavior. When user
tries to close the window, the window will be hidden. You can
then setVisible(true)
to reshow it.
DISPOSE_ON_CLOSE
: When user tries to close window,
it will be disposed.
Both HIDE_ON_CLOSE
and DISPOSE_ON_CLOSE
perform
their operations last, in case an event listener needs to use the information
from the closing event.
A JRootPane
is a container that consists of two objects, a
glass pane and a layered pane. The glass pane is initially invisible, so
all you see is the layered pane. The layered pane also consists of two
objects, an optional menu bar and a content pane. You work with the content
pane just like you would the inside of a Window
,
Dialog
, or Frame
in AWT. The way the glass pane
works is if you place a component in it, this component will always display
in front of the content pane. This allows things like popup menus and tool tip
text to work properly. The layering effect is done with the help of the new
JLayeredPane
component, explained
next.
Normally, the only difference in coding is changing all lines like:
aFrame.setLayout (new FlowLayout());
aFrame.add(aComponent);
to new lines accessing the content pane:
aFrame.getContentPane().setLayout (new FlowLayout());
aFrame.getContentPane().add(aComponent);
The rest of the panes are accessed with similar methods, though are rarely
accessed directly. The layout management of all these panes is done through
a custom layout manager.
Container getContentPane();
setContentPane (Container);
Component getGlassPane();
setGlassPane (Component);
JLayeredPane getLayeredPane();
setLayeredPane (JLayeredPane);
JMenuBar getMenuBar();
setMenuBar (JMenuBar);
The JLayeredPane
container keeps its children in layers to
define an order to paint its components. When you add a component to the
pane, you specify which layer you want it in:
layeredPane.add (component, new Integer(5));
The default layer is the value JLayeredPane.DEFAULT_LAYER
.
You can add or subtract values from this value to have things appear above
or below, layerwise. The LayoutManager
of the pane determines
what happens with the layers. Using FlowLayout
or
GridLayout
as the layout only reorders the components as they
are added; they will not be drawn on top of each other. For an example of
actually drawing overlaid components, see the examples
subdirectory that comes with the Swing release.
For applets to properly handle the Swing component set, your applets need to
subclass JApplet
instead of Applet
.
JApplet
is a special subclass of Applet
that adds
support for JMenuBar
and handles the painting support required
by Swing child components (along with any other necessary tasks like
accessibility support). Also, like JFrame
, JApplet
has a JContentPane
to add components into, instead of directly
to the applet. Another difference is the default LayoutManager
:
in JApplet
it is BorderLayout
, while in
Applet
it has always been FlowLayout
.
public class AppTester extends JApplet {
public void init () {
Container c = getContentPane();
JButton jb = new JButton ("Default");
c.add (jb, BorderLayout.WEST);
jb = new JButton ("LayoutManager");
c.add (jb, BorderLayout.CENTER);
jb = new JButton ("is");
c.add (jb, BorderLayout.EAST);
jb = new JButton ("BorderLayout: " +
(c.getLayout() instanceof BorderLayout));
c.add (jb, BorderLayout.SOUTH);
}
}
The LayoutManager
is actually a custom subclass of
BorderLayout
. This subclassing ensures that when a
component with no constraints is added, the subclass maps the
component to the CENTER
area.
A tooltip is a context-sensitive text string that is displayed
in a popup window when the mouse rests over a particular object on the
screen. Swing provides the JToolTip
class to support this;
however, you will rarely use it directly. To create a tooltip, you only
need to call the setToolTipText()
method of
JComponent
.
public class TooltipPanel extends JPanel {
public TooltipPanel() {
JButton myButton = new JButton("Hello");
myButton.setToolTipText ("World");
add(myButton);
}
}
The JToolBar
control offers a container that displays its
components in a toolbar fashion, across or down, in one row or column,
depending upon the area of the screen it is placed in. Certain user-interface
models permit floatable toolbars; the default user-interface is
one that supports floating. In order to disable the floatable capability,
just call the setFloatable()
method. It is possible that a
particular user interface may ignore this setting.
// Disabling floating
aToolBar.setFloatable (false);
When JToolBar
is considered floatable, this means a user can
drag it to another area of the screen, or place it in a window external
from the original container.
To demonstrate a JToolBar
, take a look at the following example.
As it demonstrates, there are no restrictions on what components appear within
the toolbar. However, it works best if they are all the same type and size.
public class ToolbarPanel extends JPanel {
ToolbarPanel() {
setLayout (new BorderLayout());
JToolBar toolbar = new JToolBar();
JButton myButton = new JButton("Hello");
toolbar.add(myButton);
Icon tigerIcon = new ImageIcon("SmallTiger.gif");
myButton = new JButton(tigerIcon);
toolbar.add(myButton);
toolbar.addSeparator();
toolbar.add (new Checkbox ("Not"));
add (toolbar, BorderLayout.NORTH);
toolbar = new JToolBar();
Icon icon = new AnOvalIcon(Color.red);
myButton = new JButton(icon);
toolbar.add(myButton);
icon = new AnOvalIcon(Color.blue);
myButton = new JButton(icon);
toolbar.add(myButton);
icon = new AnOvalIcon(Color.green);
myButton = new JButton(icon);
toolbar.add(myButton);
toolbar.addSeparator();
icon = new AnOvalIcon(Color.magenta);
myButton = new JButton(icon);
toolbar.add(myButton);
add (toolbar, BorderLayout.SOUTH);
}
class AnOvalIcon implements Icon {
Color color;
public AnOvalIcon (Color c) {
color = c;
}
public void paintIcon (Component c, Graphics g,
int x, int y) {
g.setColor(color);
g.fillOval (
x, y, getIconWidth(), getIconHeight());
}
public int getIconWidth() {
return 20;
}
public int getIconHeight() {
return 10;
}
}
}
After dragging around the toolbar, the user may just leave it looking a
little different than you originally planned:
Magercise
- Using Menus, Toolbars,
and Tool Tips
The JTabbedPane
component offers a tabbed control for
quick accessibility to multiple panels. If you ever tried to use
CardLayout
in JDK 1.0/1.1, you'll appreciate this:
JTabbedPane
adds the necessary support for changing from one
card to the next. After creating the control, you add cards to it with the
addTab()
method. There are three forms for the
addTab()
method. One offers a quick way to associate a
JToolTip
to a tab, while the others only permit text, an
Icon
, or both. Any Component
subclass can be
the object added to each card.
addTab(String title, Component component)
-
Create new tab with title as tab label and component
shown within tab when selected.
addTab(String title, Icon icon, Component component)
-
Adds an options icon to be associated with the title
for the tab. Either may be null
.
addTab(String title, Icon icon, Component component, String
tip)
- Adds tip as the tooltip for the tab.
public class TabbedPanel extends JPanel {
String tabs[] = {"One", "Two", "Three", "Four"};
public JTabbedPane tabbedPane = new JTabbedPane();
public TabbedPanel() {
setLayout (new BorderLayout());
for (int i=0;i<tabs.length;i++)
tabbedPane.addTab (tabs[i], null,
createPane (tabs[i]));
tabbedPane.setSelectedIndex(0);
add (tabbedPane, BorderLayout.CENTER);
}
JPanel createPane(String s) {
JPanel p = new JPanel();
p.add(new JLabel(s));
return p;
}
}
The JSplitPane
control offers user-controlled resizing of
two components within a container.
You can place a JSplitPane
within a JSplitPane
for control of more then two components, and, you can control whether the
splitting happens vertically or horizontally.
The setContinuousLayout
property causes each pane to be updated
continuously as the splitter is dragged, when set to true
.
You can move the divider programmatically by setting the
dividerLocation
property to a floating point value between
0.0 and 1.0 to indicate a percentage of the screen or to an integer value
for an absolute position.
The following screenshots demonstrate a JSplitPane
between
a JTree
and a JList
. (Note that the scrollbars
in the pictures are there because the components are included in a
JScrollPane
; it is not a result of the JSplitPane
.
The arrows on the splitter bar are obtained by setting the
oneTouchExpandable
property of the JSplitPane
to true
. Pressing them will fully push the splitter in the
direction of the arrow, or return it to its previous position.
Note that the splitter bar will not move past the minimumSize
of either component if it can avoid it. In many cases it is desirable to
call the following:
comp.setMinimumSize(new Dimension(0,0));
on each component to allow full movement of the splitter bar.
public class JSplitPanel extends JPanel {
public JSplitPanel() {
setLayout(new BorderLayout());
JTree tree = new JTree();
String[] items = {"a", "two", "three",
"four", "five", "six", "seven"};
JList list = new JList(items);
JScrollPane left = new JScrollPane(tree);
JScrollPane right = new JScrollPane(list);
left.setMinimumSize(new Dimension(0,0));
right.setMinimumSize(new Dimension(0,0));
JSplitPane pane = new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT, left, right);
pane.setDividerLocation(0.5);
pane.setOneTouchExpandable(true);
add(pane, BorderLayout.CENTER);
}
}
There are four primary Swing layout managers, two are built into components
(ScrollPaneLayout
and ViewportLayout
) and the
remaining two (BoxLayout
and OverlayLayout
) are
used like the ones from java.awt
. The BoxLayout
also happens to be built into the Box
component.
The BoxLayout
layout manager allows you to arrange
components along either an x-axis or y-axis. For instance, in a
y-axis BoxLayout
, components are arranged from top
to bottom in the order in which they are added.
Unlike GridLayout
, BoxLayout
allows
components to occupy different amounts of space along the primary
axis. A JTextField
in a top-to-bottom BoxLayout
can take much less space than a JTextArea
.
Along the non-primary axis, BoxLayout
attempts to make all
components as tall as the tallest component (for left-to-right
BoxLayout
s) or as wide as the widest component (for top-to-bottom
BoxLayout
s). If a component cannot increase to this size,
BoxLayout
looks at its Y-alignment property or X-alignment
property to determine how to place it within the available space. By default,
JComponent
objects inherit an alignment of 0.5 indicating that
they will be centered. You can override the getAlignmentX()
and
getAlignmentY()
methods of Container
to specify a
different default alignment. JButton
for instance specifies left
alignment.
To create a BoxLayout
, you must specify two parameters:
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
The first parameter specifies the container and the second the major axis
of the BoxLayout
. Components can then be added as they are in
a GridLayout
or FlowLayout
:
add(myComponent);
class BoxLayoutTest extends JPanel {
BoxLayoutTest() {
// Set the layout to a y-axis BoxLayout
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
// Create three components
TextField textField = new TextField();
TextArea textArea = new TextArea(4, 20);
JButton button = new JButton(
"Tiger", new ImageIcon("SmallTiger.gif"));
// Add the three components to the BoxLayout
add(new JLabel("TextField:"));
add(textField);
add(new JLabel("TextArea:"));
add(textArea);
add(new JLabel("Button:"));
add(button);
}}
The Box
class is a convenience container whose default
layout manager is a BoxLayout
. Rather than subclassing
JPanel
as above, the previous example could have subclassed
the Box
class. In addition to being a BoxLayout
container, Box
has some very useful static methods for
arranging components in a BoxLayout
. These methods create
non-visual components that act as fillers and spacers.
createVerticalStrut(int) |
Returns a fixed height component used for spacing |
createHorizontalStrut(int) |
Returns a fixed width component used for spacing |
createVerticalGlue() |
Returns a component whose height expands to absorb
excess space between components |
createHorizontalGlue() |
Returns a component whose width expands to absorb
excess space between components |
createGlue() |
Returns a component whose height will expand for a
y-axis box and whose width will expand for an x-axis Box |
createRigidArea(Dimension) |
Returns a fixed height, fixed width component used for spacing |
Now, rather than using labels to space components out as above, you could
use struts and glue:
public class TestBox extends Box {
TestBox() {
super(BoxLayout.Y_AXIS);
// Create the three basic text components
TextField textField = new TextField();
TextArea textArea = new TextArea(4, 20);
JButton button = new JButton("Tiger", new
ImageIcon("SmallTiger.gif"));
// Separate the three components
// by struts for spacing
add(createVerticalStrut(8));
add(textField);
add(createVerticalGlue());
add(textArea);
add(createVerticalGlue());
add(button);
add(createVerticalStrut(8));
}
}
The struts will appear as top and bottom margins and the glue will expand
to fill space when the Box
is heightened.
Magercise
- Using BoxLayout
The ScrollPaneLayout
is the layout manager used by a
JScrollPane
. You do not need to create one, nor associate
it to the JScrollPane
. That is done for you automatically.
The layout defines nine different areas for the JScrollPane
:
- one
JViewport
- in the center for the content
- two
JScrollBar
objects - one each for horizontal
and vertical scrolling
- two
JViewport
objects - one for a column headers,
the other row
- four
Component
objects - one for each of the corners
The JScrollPane
constants to specify the corners are:
LOWER_LEFT_CORNER
, LOWER_RIGHT_CORNER
,
UPPER_LEFT_CORNER
, UPPER_RIGHT_CORNER
.
The center viewport portion of this layout is of primary interest for
simple layouts. A JViewport
is itself a container object
that can hold components. This allows for some very flexible arrangements.
JViewport
contains its own layout manager,
ViewportLayout
.
ViewportLayout
is the layout manager used by a
JViewport
. You should never need to use the layout directly,
as it is automatically associated with a JViewport
object,
and positions the internal component for you based upon the
JViewport
properties.
While this may seem like quite a bit for Swing, there is much more to see,
do, and learn. To follow the latest Swing-related happenings, be sure to
visit Sun's online technical resource
The Swing Connection.
Certain topics you should be sure not to miss:
Copyright © 1998-1999
MageLang Institute.
All Rights Reserved.