The Swing collection of components is quite large (see this visual
index) and they offer a wide range of functions and features.
The various layout managers discussed in Chapter
7: Java provide for a great diversity of arrangements of these
components. Panels can hold multiple sub-panels, each with its own
layout manager and set of components. So with these Swing tools you
can build very elaborate and feature rich user interfaces for your
programs.
Howerver, the appearance of the interfaces displayed
in the various examples so far may appear somewhat boring. We will
give a brief introduction here to some of the techniques available
for modifying the appearance of the components and the border areas
between the components. See the references below for links to tutorials
that provide more information and examples for these techniques.
We also briefly mention some functionality enhancements as well.
For the four demonstration programs below, we started
with the GridBagLayout example from Chapter
7: Java: Layouts.
Insets
The dimensions of the border area of a container component are
found from its Insets object. The border
values are given by the integer fields top,
left, bottom,
right. An insets object can be created
by passing the border values as follows:
Insets(int top, int left, int bottom,
int right)
In our first example, GridBagLayoutV1,
we create a static Insets object in
static
final Insets fInsets = new Insets(2,2,2,2);
and then set the appropriate field in the GridBagConstraints
object:
constraints.insets
= fInsets;
Comparing this interface with the original
demo, we see that this puts a border gap around the components
in the layout. You can vary this gap by modifiying the constraints
insets value before adding each component.
For the component in the top right corner the border area is much
larger. For that one we decided to manipulate its border directly.
We created a panel with a wide border and then added the button
to it. The button will be constrained within the thicker border
area.
The method getInsets(), inherited from
Container, returns an Insets
object with the current border values for that component.
Insets insets = myContainer.getInsets
();
It might seem logical that if you want to change the border dimensions,
you would create an Insets object with
the desired dimensions and pass it via a setInsets()
method. However, there is no a setInsets()
method. (We will show in the next example how to set a border explicitly.)
For this case, we modify the Insets for
the panel by creating a subclass of panel (called MyNewInsetsPanel
) that overrides the getInsets() method
and returns an Insets object with the
desired dimensions. The layout manager will invoke this method when
it is calculating how to layout the component.
The source code for GridBagAppletV1
and its panel class GridBagPanel
is shown below. The sections of code that differ from
GridBagApplet
are shown in red.
GridBagLayoutV1
|
/** First modification of GridBagLayout involves using insets
to put
* space around the components.
**/
public class GridBagAppletV1 extends JApplet {
public void init () {
Container content_pane = getContentPane
();
// Create an instance of the GridBagPanel
GridBagPanelV1 grid_bag_panel =
new GridBagPanelV1 ();
// And add it to the applet's panel.
content_pane.add (grid_bag_panel);
} // init
} // GridBagAppletV1
/** Create a JPanel with 5 buttons and use GridBagLayout
manager.**/
class GridBagPanelV1 extends JPanel {
GridBagConstraints constraints = new GridBagConstraints
();
// The Insets constructor
setting are passed as follows:
// Insets(int top, int left, int bottom, int
right)
static final Insets fInsets = new Insets(2,2,2,2);
GridBagPanelV1 () {
setLayout (new GridBagLayout ());
// Create a 3 row grid
// Fill the grid squares with the
component
// in both x and y directions
constraints.fill = GridBagConstraints.BOTH;
// Keep same weight in vertical
dimension
constraints.weighty = 1.0;
// Top row will include three components,
each
// weighted differently in x
// 0,0
constraints.weightx = 1.0;
constraints.gridx = 0; constraints.gridy
= 0;
// We will
use the same Insets object for the constraints
// for each component.
constraints.insets = fInsets;
add (new JButton ("0,0"), constraints);
//
0,1
constraints.weightx = 0.5;
constraints.gridx = 1; constraints.gridy
= 0;
add (new JButton ("1,0"), constraints);
// 0,2
constraints.weightx = 0.1;
constraints.gridx = 2; constraints.gridy
= 0;
JButton button20 = new JButton ("2,0");
JPanel button20_panel =
new MyNewInsetsPanel
(new BorderLayout ());
button20_panel.add (button20);
add (button20_panel, constraints);
// Middle row has two components. First takes
up two
// rows, second takes up two columns
// The first component on second
row will span
// vertically to third row
// 0,1 to 0,2
constraints.weightx = 1.0;
constraints.gridx = 0; constraints.gridy
= 1;
constraints.gridheight = 2;
add (new JButton ("0,1 to 0,2"),
constraints);
// The second component on second
row will span
// horizontally to third column
// 1,1 to 2,1
constraints.weightx = 1.0;
constraints.gridx = 1; constraints.gridy
= 1;
constraints.gridheight = 1;
constraints.gridwidth =
2;
add (new JButton ("1,1 to 2,1"),
constraints);
// Bottom row has 2 components with fill set
to NONE
// Use anchor.
constraints.fill = GridBagConstraints.NONE;
// 1,2
constraints.anchor = GridBagConstraints.SOUTHEAST;
constraints.weightx = 0.5;
constraints.gridx = 1; constraints.gridy
= 2;
constraints.gridheight = 1;
constraints.gridwidth =
1;
add (new JButton ("1,2"), constraints);
// 2,2
constraints.anchor = GridBagConstraints.WEST;
constraints.weightx = 0.1;
constraints.gridx = 2; constraints.gridy
= 2;
constraints.gridheight = 1;
constraints.gridwidth =
1;
add (new JButton ("2,2"), constraints);
} // ctor
} // class GridBagPanelV1
/** Simple JPanel subclass to demonstrate
how to
* override getInsets to modify the border size.
**/
class MyNewInsetsPanel extends JPanel {
public MyNewInsetsPanel (LayoutManager layout)
{
super (layout);
}
public Insets getInsets () {
return new Insets (5,10,5,10);
}
} // MyNewInsetsPanel
|
Border
Swing provides for much more elaborate control of the border than
simple modifying the insets dimensions. Decorative and non-decorative
borders for Swing components can be created with the Border
class and the setBorder() method in the
JComponent class.
Note that generally, it is best to manipulate the borders only
of panels and labels. You can always add other kinds of components
to a panel with the border that you desire.
In the GridBagAppletV2
demo shown below, we show examples of some of the types of borders
you can create. See How
to Use Borders - Sun Java Tutorial for a more detailed introduction
to making borders and for examples of border types not shown here.
Again we show in red the new code. We create seven Border
objects using the factory methods in the Border
class. The first case is an empty border that provides an empty
margin area similar to what could be obtained from the insets technique
used above.
Border
empty_border = BorderFactory.createEmptyBorder (10,5,10,5);
A panel is created and the border set to this one:
empty_border_panel.setBorder
(empty_border);
We next use a similar procedure to create a rasied-bevel border
and a red line border. The fourth case adds a title to the red line
border. The fifth creates a compound border made from a combination
of the red line and raised bevel border.
The final two examples use matte borders created from image icons
(Note that we now pass a reference for the applet to the GridBagPanelV2
constructor for the convenience of using the getImage()
method available from the applet class for obtaining the image file
for icon.)
GridBagLayoutV2
Resources: bluebox.jpg,
redDot.gif
|
import
javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.border.*;
/**
* Our second modification to GridBagLayout involves
* setting borders for the components..
**/
public class GridBagAppletV2 extends JApplet{
public void init () {
Container content_pane = getContentPane
();
// Create an instance of the GridBagPanel
GridBagPanelV2 grid_bag_panel =
new GridBagPanelV2 (this);
// And add it to the applet's panel.
content_pane.add (grid_bag_panel);
} // init
} // GridBagAppletV2
/**
* Create a JPanel with 5 components and use
GridBagLayout for the
* overall layout.
**/
class GridBagPanelV2 extends JPanel {
GridBagConstraints constraints = new GridBagConstraints
();
// The Insets constructor setting are passed
as follows:
// Insets(int top, int left, int bottom, int
right)
static final Insets fInsets = new Insets(2,2,2,2);
GridBagPanelV2 (JApplet
applet) {
setLayout (new GridBagLayout ());
// Create a 3 row grid
// Fill the grid squares with the
component
// in both x and y directions
constraints.fill = GridBagConstraints.BOTH;
// Keep same weight in vertical
dimension
constraints.weighty = 1.0;
// Top row will include three components,
each
// weighted differently in x
// 0,0
constraints.weightx = 1.0;
constraints.gridx = 0; constraints.gridy
= 0;
constraints.insets = fInsets;
// Use the
empty border for a panel to put a margin area
// around the button placed on the
panel.
// The arguments go as
// createEmptyBorder(int
top, int left, int bottom, int right)
Border empty_border = BorderFactory.createEmptyBorder
(10,5,10,5);
// User BorderLayout so the button
will fill the whole panel area.
JPanel empty_border_panel = new
JPanel (new BorderLayout ());
// Set the border for the panel
empty_border_panel.setBorder (empty_border);
// Add the button to the panel
empty_border_panel.add (new JButton
("0,0"));
// Finally, add the panel to the
larger GridBagPanel
add (empty_border_panel, constraints);
// 0,1
constraints.weightx = 0.5;
constraints.gridx = 1; constraints.gridy
= 0;
// Put a raised
bevel border on a panel.
Border raised_bevel =BorderFactory.createRaisedBevelBorder();
JPanel raised_bevel_panel = new
JPanel (new BorderLayout ());
raised_bevel_panel.setBorder (raised_bevel);
// Then place a button on the panel.
raised_bevel_panel.add (new JButton
("1,0"));
add (raised_bevel_panel,
constraints);
// 0,2
constraints.weightx = 0.1;
constraints.gridx = 2; constraints.gridy
= 0;
// Create
a red line border for the panel
Border red_border = BorderFactory.createLineBorder(Color.RED);
JPanel red_border_panel = new JPanel
(new BorderLayout ());
red_border_panel.setBorder (red_border);
red_border_panel.add (new JButton
("2,0"));
add (red_border_panel, constraints);
// Middle row has two components. First takes
up two
// rows, second takes up two columns
// The first component on second
row will span
// vertically to third row
// 0,1 to 0,2
constraints.weightx = 1.0;
constraints.gridx = 0; constraints.gridy
= 1;
constraints.gridheight = 2;
// Create
a title border using the previous red line border.
TitledBorder title_border = BorderFactory.createTitledBorder(
red_border,
"Title Goes Here");
JPanel title_border_panel = new
JPanel (new BorderLayout ());
title_border_panel.setBorder (title_border);
title_border_panel.add (new JButton
("0,1 to 0,2"));
add (title_border_panel,
constraints);
// The second component on second
row will span
// horizontally to third column
// 1,1 to 2,1
constraints.weightx = 1.0;
constraints.gridx = 1; constraints.gridy
= 1;
constraints.gridheight = 1;
constraints.gridwidth =
2;
// Create
a compound border of the red line and raised bevel borders
Border compound_border = BorderFactory.createCompoundBorder(red_border,
raised_bevel);
JPanel compound_border_panel = new
JPanel (new BorderLayout ());
compound_border_panel.setBorder
(compound_border);
compound_border_panel.add (new JButton
("1,1 to 2,1"));
add (compound_border_panel,
constraints);
// Bottom row has 2 components with fill set
to NONE
// Use anchor.
constraints.fill = GridBagConstraints.NONE;
// 1,2
constraints.anchor = GridBagConstraints.SOUTHEAST;
constraints.weightx = 0.5;
constraints.gridx = 1; constraints.gridy
= 2;
constraints.gridheight = 1;
constraints.gridwidth =
1;
// Will use
a small image to create an matte border.
try {
// Read in the image
and create and icon.
ImageIcon icon = new
ImageIcon (
new java.net.URL
(applet.getCodeBase (), "redDot.jpg") );
JPanel matte_panel =
new JPanel (new BorderLayout ());
matte_panel.setBorder
(
BorderFactory.createMatteBorder
(20, 20, 20, 20, icon));
matte_panel.add (new
JButton ("1,2"));
add (matte_panel, constraints);
}
catch (java.net.MalformedURLException
mue)
{}
// 2,2
constraints.anchor = GridBagConstraints.WEST;
constraints.weightx = 0.1;
constraints.gridx = 2; constraints.gridy
= 2;
constraints.gridheight = 1;
constraints.gridwidth =
1;
// Another
matte border with a smaller image.
try {
ImageIcon icon =
new ImageIcon
(new java.net.URL (applet.getCodeBase (),
"blueBox.jpg") );
JPanel matte_panel =
new JPanel (new BorderLayout ());
matte_panel.setBorder
(
BorderFactory.createMatteBorder
(10, 10, 10, 10, icon));
matte_panel.add (new
JButton ("2,2"));
add (matte_panel, constraints);
}
catch (java.net.MalformedURLException
mue)
{}
} // ctor
} // class GridBagPanelV2
|
Icons
in Components
Another enhancement for user interfaces is to add icons to buttons
and labels. In the first two buttons of GridBagApplet
shown below, we pass via the button constructor the icon for the
normal, unpressed state. Another icon for the pressed state is passed
via the setPressed() method. For the second
case we also set the fill parameter to NONE to eliminate the margin
space around the icon.
The third component is replaced with a label on which we put an
icon and also text. We make the background of the label opaque and
then set it to yellow.
For the fourth case we put both an icon and text on the button.
The other components are unchanged.
GridBagLayoutV3
Resources: bluebox.jpg,
picButton.jpg,
picButtonPressed.jpg,
face.gif,
redBall.gif,
redDot.gif
|
import
javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.border.*;
/**
* Our third modification to GridBagLayout involves
adding
* icons to buttons and labels.
**/
public class GridBagAppletV3 extends JApplet{
public void init () {
Container content_pane = getContentPane
();
// Create an instance of the GridBagPanel
GridBagPanelV3 grid_bag_panel =
new GridBagPanelV3 (this);
// And add it to the applet's panel.
content_pane.add (grid_bag_panel);
} // init
} // GridBagAppletv3
/**
* Create a JPanel with 5 components and use
GridBagLayout
* for the overall layout.
**/
class GridBagPanelV3 extends JPanel {
GridBagConstraints constraints = new GridBagConstraints
();
// The Insets constructor setting are passed
as follows:
// Insets(int top, int left, int bottom, int
right)
static final Insets fInsets = new Insets(2,2,2,2);
// Need a reference back to the applet to use
it for getting images.
JApplet fApplet;
GridBagPanelV3 (JApplet applet) {
fApplet = applet;
setLayout (new GridBagLayout ());
// Create a 3 row grid
// Fill the grid squares with the
component
// in both x and y directions
constraints.fill = GridBagConstraints.BOTH;
// Keep same weight in vertical
dimension
constraints.weighty = 1.0;
// Top row will include three components,
each
// weighted differently in x
// 0,0
constraints.weightx = 1.0;
constraints.gridx = 0; constraints.gridy
= 0;
constraints.insets = fInsets;
// Use the empty border for a panel
to put a margin area
// around the button placed on the
panel.
Border empty_border = BorderFactory.createEmptyBorder
(10,5,10,5);
// User BorderLayout so the button
will fill the whole panel area.
JPanel empty_border_panel = new
JPanel ();
empty_border_panel.setBorder (empty_border);
// Get an
icon for the button in an unpressed state.
ImageIcon icon = getIcon ("picButton.jpg");
// Create the button with an icon and
no text.
JButton button00 = new JButton (icon);
// Get the icon for the pressed button
state
ImageIcon icon_pressed = getIcon ("picButtonPressed.jpg");
// Now pass the press icon to the button.
button00.setPressedIcon (icon_pressed);
empty_border_panel.add (button00);
add (empty_border_panel, constraints);
// 0,1
// To get
rid of the gap around the icon, set the fill to NONE.
constraints.fill = GridBagConstraints.NONE;
constraints.weightx = 0.5;
constraints.gridx = 1; constraints.gridy
= 0;
// Put a raised bevel border on
a panel.
Border raised_bevel =BorderFactory.createRaisedBevelBorder();
JPanel raised_bevel_panel = new
JPanel (new BorderLayout ());
raised_bevel_panel.setBorder (raised_bevel);
// Again set
the icons for the unpressed and pressed button states.
JButton button10
= new JButton (icon);
button10.setPressedIcon (icon_pressed);
button10.setMargin (new Insets (0,0,0,0));
// Then place a button on
the panel.
raised_bevel_panel.add (button10);
add (raised_bevel_panel,
constraints);
// 0,2
constraints.weightx = 0.1;
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 2; constraints.gridy
= 0;
// Create a red line border for
the panel
Border red_border = BorderFactory.createLineBorder(Color.RED);
JPanel red_border_panel = new JPanel
(new BorderLayout ());
red_border_panel.setBorder (red_border);
// Use
a label instead of a button. Pass the text and icon and
tell
// it to center both off them
icon = getIcon ("redBall.gif");
// Make the label background to
opaque
JLabel red_ball_label =
new JLabel ("2,0",
icon, SwingConstants.CENTER);
// Make the label background to
opaque
red_ball_label.setOpaque (true);
// and then set the color of the
background.
red_ball_label.setBackground (Color.YELLOW);
red_border_panel.add (red_ball_label);
add (red_border_panel, constraints);
// Middle row has two components. First takes
up two
// rows, second takes up two columns
// The first component on second
row will span
// vertically to third row
// 0,1 to 0,2
constraints.weightx = 1.0;
constraints.gridx = 0; constraints.gridy
= 1;
constraints.gridheight = 2;
// Create a title border using the
previous red line border.
TitledBorder title_border = BorderFactory.createTitledBorder(
red_border,
"Title Goes Here");
JPanel title_border_panel = new
JPanel (new BorderLayout ());
title_border_panel.setBorder
(title_border);
icon = getIcon ("face.gif");
title_border_panel.add (new JButton
("0,1 to 0,2", icon));
add (title_border_panel,
constraints);
// The second component on second
row will span
// horizontally to third column
// 1,1 to 2,1
constraints.weightx = 1.0;
constraints.gridx = 1; constraints.gridy
= 1;
constraints.gridheight = 1;
constraints.gridwidth =
2;
// Create a compound border of the
red line and raised bevel borders
Border compound_border =
BorderFactory.createCompoundBorder(red_border,
raised_bevel);
JPanel compound_border_panel = new
JPanel (new BorderLayout ());
compound_border_panel.setBorder
(compound_border);
compound_border_panel.add (new JButton
("1,1 to 2,1"));
add (compound_border_panel,
constraints);
// Bottom row has 2 components with fill set
to NONE
// Use anchor.
constraints.fill = GridBagConstraints.NONE;
// 1,2
constraints.anchor = GridBagConstraints.SOUTHEAST;
constraints.weightx = 0.5;
constraints.gridx = 1; constraints.gridy
= 2;
constraints.gridheight = 1;
constraints.gridwidth =
1;
icon = getIcon ("redDot.gif");
JPanel matte_panel = new JPanel
(new BorderLayout ());
matte_panel.setBorder (
BorderFactory.createMatteBorder
(10, 10, 10, 10, icon));
matte_panel.add (new JButton ("1,2"));
add (matte_panel, constraints);
// 2,2
constraints.anchor = GridBagConstraints.WEST;
constraints.weightx = 0.1;
constraints.gridx = 2; constraints.gridy
= 2;
constraints.gridheight = 1;
constraints.gridwidth =
1;
icon = getIcon ("blueBox.jpg");
matte_panel = new JPanel (new BorderLayout
());
matte_panel.setBorder (
BorderFactory.createMatteBorder
(10, 10, 10, 10, icon));
matte_panel.add (new JButton ("2,2"));
add (matte_panel, constraints);
} // ctor
ImageIcon getIcon (String icon_name) {
ImageIcon icon;
try {
icon = new ImageIcon
(new java.net.URL (
fApplet.getCodeBase (), icon_name) );
}
catch (java.net.MalformedURLException
mue)
{ return null; }
return icon;
} // getIcon
} // class GridBagPanelV3
|
Continue to UI Enhancements:
Part 2...
References & Web Resources
Latest update: Nov. 3, 2006
|