Common Swing
Components & Containers
Peter Komisar  ©  Conestoga College   latest version  5.8 / 2010

// additional reference: 'Graphic Java' by Dave Geary


Swing & AWT Overview



Early AWT

In some respects, AWT or the Abstract Windowing Toolkit was
really not ready for prime-time when Java exploded into popularity
circa 1996. AWT was designed as a peer based architecture.
AWT 'widgets' act as wrappers for native platform components.
At the time the one-to-one ratio of peer-based to native components
resulted in poor performance. This performance issue is really now
gone given the power of today's machines.

A more important problem arose from the differences between native
components on different platforms. Consistent cross platform appearance
was elusive, threatening to sink one of Java's touted claims to 'cross
platform' portability. In the early days AWT still had a fair number of
garden-variety 'bugs' that needed fixing.

IFC, Internet Foundation Classes

Netscape had built conceptually on NextStep's visual toolkit to produce
the IFC, or the Internet Foundation Classes. Sun made a deal with
Netscape, and together with Apple and IBM ported the IFC toolkit to
Java. Swing has since evolved to the point that it's relationship to the
original Internet Foundation Classes has become distant.

Swing replaced AWT's heavyweight components with a set of lightweight
components and in addition, added a large number of new components.
Today there are are over 40 components that utilize over 250 classes.

The following tutorial by the then, Magelang institute, on the Sun web site
has faithfully maintained on the web since the early days of Java and is a
useful reference that shows diagrams of the various Swing components.

Link to Tutorial that Diagrams the Swing Framework

http://java.sun.com/developer/onlineTraining/GUI/Swing1/shortcourse.html


Swing Builds On Rather Than Replaces AWT

Swing still uses AWT resources such as graphics, color management,
fonts and layout managers. Swing also uses heavyweight container for
the their initial builds. These heavy-weight classes are built as extensions
of their peer based counterparts in AWT, (namely JFrame, JWindow,
JDialog and JApplet .) Thus, Swing builds on AWT rather than relegating
it to the dust bin.



Issues Related to Mixing AWT and Swing Components



Something New In Java 6 ( Update 12 )

Before Java 6 Swing and AWT components did not mix well.
This was due to the different natures of the components. The
long and short was that AWT widgets  were peer based and
as such opaque, when sharing space with 'lightweight' peerless
Swing components. This resulted in AWT components always
appearing 'on top' of Swing components when mixed.

Time moves on and the Java developers introduced a fix for
this problem in Java 6. Now when components are mixed from
the two APIs they behave properly. A lot of textbooks will need
revision!

This was discovered when showing the example below in class
where the intended bad behavior or mixing AWT and Swing
components had disappeared.

The Story As Applies to Versions of Java Older Than JDK 1.6 Update 12

To reiterate, before JDK 1.6, The problem with mixing AWT heavyweight
widgets and Swing lightweight controls comes from the fact that all AWT
component, based on native widgets, are 'opaque'. That is they are
not transparent.

Swing components are by nature lightweight and 'transparent' (at least
relative to a heavyweight component). The result is that if a Swing
component is layered on top of an AWT component, the AWT component
appears to be on top of the Swing component.


Z-order
  // high order, think 'on top of'

'Z Order' (sometimes called  'zorder'  or z-order ) is a term that
represents the layering depth at which components appear with
respect to other components in the same container.

Think of a deck of cards. Each card has a different z-order
value. This 'z'  is similar to one used in 3-D Cartesian graphs.

The first component added to a container takes the highest z-order
value and appears at the top of the stack
. The last component added
adopts the lowest 'z-order' number value and is placed at the bottom
of the stack.

Diagram depicting the relationship between component adding and z-ordering


// assume components are added to a layered component like JFrame

 AWT first Added Component        // highest z-order value
 AWT intermediate Components    // intermediate numbers
 AWT last Component Added        // lowest z-order value
 
____________________________________________________________________

  AWT peer based component appear on top of Swing 'lightweight' components

  // that was before ( JDK 1.6 Update 12 )  ____________________________________________________________________

 Swing first Added Component      // highest z-order value
 Swing intermediate Components  // intermediate numbers
 Swing last Component Added      // lowest z-order value


Z-order values are not published as being accessible so they only
provide us with a theoretical description of how elements are layered
using z-order values.

The following code, before JDK 1.6, use to illuminates the idea of z-order
as well as mixing light and heavyweight components. You will need to use
a JRE from JDK 1.5 to make the code work as first intended. Where the
AWT components do not layer sequentially with the Swing components. 


Z-Order and Mixing Light and Heavyweight Components

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class Layers extends JFrame{
     JLabel label1, label2, label3, narrative, narrative2;
     Label label4, label5, label6;
     // JPanel panel;
      Layers(String s){
         super(s);
        
         JPanel panel = new JPanel();
         panel.setLayout(null);
     
     label1= new JLabel(" Swing JLabel 1");
     label1.setOpaque(true);
     label1.setBackground(Color.yellow);
     label1.setBounds(20,20,250,50);
     
     label2= new JLabel(" Swing JLabel 2");
     label2.setOpaque(true);
     label2.setBackground(Color.pink);
     label2.setBounds(40,60,250,50);
   
     label3= new JLabel(" Swing JLabel 3");
     label3.setOpaque(true);
     label3.setBackground(Color.gray);
     label3.setBounds(60,100,250,50);   

// added in order
    
     panel.add(label1);
     panel.add(label2);
     panel.add(label3);
     
     // AWT heavy weight components added next
     // keeping same pattern notice AWT is already
     // opaque so these lines don't apply to AWT!
     
     label4= new Label(" AWT Label 4");
    // label4.setOpaque(true);
     label4.setBackground(Color.orange);
     label4.setBounds(80,140,250,50);
   
     label5= new Label(" AWT Label 5");
    // label5.setOpaque(true);
     label5.setBackground(Color.lightGray);
     label5.setBounds(100,180,250,50);
     
     label6= new Label(" AWT Label 6");
    // label6.setOpaque(true);
     label6.setBackground(Color.white);
     label6.setBounds(120,220,250,50);

     narrative = new JLabel(" Before JDK 1.6 The AWT #4 label would overlap Swing Label #3. ");
     narrative2 = new JLabel(" Otherwise Z order was maintained. Now the components can mix!");
     
     // leave transparent
     narrative.setBounds(20, 300, 400, 60);
     narrative2.setBounds(20,320, 400, 60);     
     
     panel.add(label4);
     panel.add(label5);
     panel.add(label6);
     panel.add(narrative);
     panel.add(narrative2);
     getContentPane().add(panel);
     setSize(500,500);
     setVisible(true);
     }
     public static void main(String[]args){
     new Layers("Mixing AWT & Swing Components");
     }
     }

With respect to components of the same type, AWT or  Swing, z-order
is respected, however AWT components will always appear to have
a higher z-order value than a lightweight Swing component when the
two types are mixed.

There were a set of suggestions provided by Dave Geary which are
explained at length in his book, 'Graphics Java'. While perhaps no
longer needed, the guidelines would apply for backwards compatibility
and perhaps still should still be followed, if you are in a situation where
you have to work with both sorts of components in a single GUI.
The suggestions are paraphrased below.

Dave Geary's Suggestions When Mixing Heavy & Light
Components  ( Applying to Java version JDK 1.6 Update 12 )

- if a lightweight component needs to appear on top of
a
heavyweight component don't mix the component types

- if a popup menu intersects a heavyweight component
  force
the popup to be heavyweight

- don't add heavyweight components to JScrollPane
   // doesn't clip properly

- don't add heavyweight components to internal frames
  // topmost frame is obscured

A more general rule, avoid mixing AWT and Swing! Even with
JDK 1.6 this suggestion is probably still a good idea to heed. 



Swing Component Overview



The Swing components are a big improvement on AWT
components for a number of reasons.
Swing allows
the creation of sophisticated GUI features such as the
ability to add icons
to components, to set 'tool tips' that
respond to mouse-overs, to drag and drop items
and to
add layered pop-up menus and dialog boxes into GUIs.

New Features That Come with Swing


In
addition to creating a new set of J-prefixed Swing
components to replace each of the
peer-based AWT
components,  the Swing library adds a number of new
Swing
components to extend the capabilities of Java
graphical user interfaces.

//  ( J + AWT ) components  + new Swing Components

The numerous Swing components are in general easy to
use. They can be classified
by a number of schemes. The
component hierarchy itself supplies the most logical system

of organizing these components.

Text, Button, Panel and Container Components

We find in Swing and AWT, there is a group of visual components
that work with text. These all descend from JTextComponent.
There is another group of controls
based on the button theme
which have the parent, AbstractButton. Another set is based
on the panel concept. There is also a
group of container classes
that share a common ancestry.

Complex Components

A few complex components are unique and 'stand-alones'.
Components such as JList, JTree and
JTable are quite
complex and deserve to be singled out and treated 
with
special attention. There are also a number of components
that are one-of-a kind
and do not fit into a group. For instance
JLabel, which has the job of labeling GUIs.
There really only
needed to be one of these.

A classification can be made of components that are used
across the board. For instance borders and icons are used
by all  components. We can treat these kinds of components
as a group in their own rite.

Classifying Swing Components



Commonly Shared Elements, Borders & Icons



'Trans-Class' Components

Components such as borders, icons and tooltips may
be used by all the Swing components. Consider the
tooltip class.


Tooltips

A tooltip is a short pop-up text which appears over top
of a GUI when the mouse
wands over a component.
There is a JToolTip class, however, for convenience a
method
called setToolTipText( ) has been added to
JComponent. This component enables a tooltip to be

easily added for any visual component.


Example   

JButton myButton = new JButton("Accept");
myButton.setToolTipText ("Press to confirms the purchase");

 

Lets insert code a tool tip sample and not worry
about details of components or
syntax that we
haven't encountered yet. This build is all done
inside the main( ) method.


Code Sample With a Focus on Setting Tooltips

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class SwingDemo{
public static void main(String[] args){
JFrame frame = new JFrame( );
// circa JDK1.4  a nice close operation was introduced
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton acceptButton = new JButton("Accept");
acceptButton.setToolTipText ("Press to confirms the purchase");
// we will talk about JFrame's layers
Container content = frame.getContentPane( );
content.add(acceptButton);
// frame needs setting for size and visibility
frame.setSize(600,300);
frame.setVisible(true);
}
}


Icon & ImageIcon

Icons are miniature pictures that can be embedded in
components. They are Java Image class objects that
have been processed in a way that binds them to the
component. The component can be serialized and sent
down a wire and the image will go with it and not need
special classes to reconstitute it as an ordinary Image
object requires.

// image element will serialize with the component

Icons can be added in a similar manner to all Swing
components. Icon is an interface that defines three
methods. By supplying implementations for these three
methods, a
custom graphic can be created and applied
to the Swing components you deploy.

Here you see again an example of an interface. We
discussed interfaces in the previous note.
 

The Icon interface Definition

public interface Icon {
      void paintIcon(
          Component c, Graphics g, int x, int y);
          int getIconWidth( );
          int getIconHeight( );
          }

Because most images a designer uses in a Swing GUI
will be GIF (.gif ), PNG, (.png) or JPEG ( .jpg )  files, the
Swing developers have supplied a default implementation
of the Icon interface, the class, ImageIcon.

ImageIcon has several constructors allowing an image to
be supplied as a file, an array or a URL. The class is usually
declared to the type of the Icon interface.

// png files are also now supported, sometimes at or before JDK 1.6


Example
         

Icon miniature = new ImageIcon("AuntSarahLee.jpg");

// ImageIcon constructors may receive files, arrays or URLs.

 
Another example shows a Hubble telescope shot of the
'Bug Nebula' inserted as an icon.


Example 2     

ImageIcon icon = new ImageIcon("images/bugnebula.jpg");
JLabel label2= new JLabel(icon); 

We see shortly how easy it is to set this icon into a visual
component.

We can include a custom implementation of Icon here,
just to get some complete Java code into the discussion.
( Apologies, this is not art! ).

Example of a Custom Implementation of the  Icon Interface

// for the moment use Ctrl-C to exit DOS Process

import javax.swing.*;
import java.awt.*;

// a class that implements the Icon Interface

class SimpleIcon implements Icon{
       public int getIconWidth( ){
            return 20;             }
       public int getIconHeight( ){
            return 20;
            }
      
 public void paintIcon(Component c, Graphics g, int x, int y){
      
        g.setColor(Color.red);
        g.fillRect(10,10,30,10);
        g.setColor(Color.gray);
        g.fillRect(20,22,10,16);
        g.setColor(Color.red);
        g.fillRect(10,40,30,10);
      }
   }

// a 'runner' class that that shows a JLabel including the Icon object

class IconShow extends JFrame{

       IconShow( ){
          Icon icon = new SimpleIcon();
          JLabel label = new JLabel
          ("Simple Icon In a JLabel", icon, SwingConstants.CENTER);
          JFrame frame = new JFrame();
          getContentPane().add(label);
          setSize(200,200);
          setVisible(true);
          }
    public static void main(String[]args){
         new IconShow();
         }
   }

 

Borders

Swing components have borders that can be set to factory
default values or can be customized in a way similar to the
example shown for the Icon interface. Borders are supplied
to components via the Border interface. Border interface
defines a number of methods specifically designed to draw
borders on components. The tools for customizing borders
are housed in the javax.swing.border package. The package
stores several classes that implement the Border interface in
different ways to provide stock choices to the designer.
Following is the Border interface and the three methods
it defines.

// Border interface, javax.swing.border package
 

The Border interface

interface Border
           {

           public Insets getBorderInsets(Component c)
           public boolean isBorderOpaque( )

           public void paintBorder (Component c, Graphics g, int x,
           int
y, int width, int height )
           }

The paintBorder method paints the component's border with
the specified border
and size. The getBorderInsets method
returns the insets for the 'drawable' area of
the component
supplied. The isBorder method returns a boolean to indicate

whether the border area is opaque or transparent.
 

The Border Package

AbstactBorder
      |___BevelBorder
      |       |___ SoftBevelBorder
      |
      |______CompoundBorder
 
     |
      |______EmptyBorder
      |          |____ MatteBorder
      |

      |______EtchedBorder
      |______LineBorder
      |______TitledBorder

 

// the convenience method setBorder( ) makes applying borders easy


JComponent Implements Border

JComponent implements Border so all of it's subclasses
inherit the same border behavior. JComponent also defines
the setBorder( ) method for conveniently changing the
default border to another border selection. Swing defines
the parent AbstractBorder that you can use to implement
custom borders as well as eight preset descendants the
programmer can use for 'off the shelf' effects.

// 8 presets plus one abstract parent usable for custom borders
// presets can also be extended


Creating Borders Using BorderFactory

There are a few approaches that can be taken to create
borders. One method uses the createXXXBorder( ) methods
of the BorderFactory class. This class is stored in javax.swing
unlike the border classes listed below which are in the
javax.swing.border package. BorderFactory can create
different border types via static methods named after each
of the predefined Border class.
 

Example  

Border border =
BorderFactory.createEtchedBorder(Color.gray, Color.white);

JButton jb= new JButton("Button");
jb.setBorder(border);

This is a convenient technique for defining a border once
and then easily adding it to other components in a GUI.
The different pre-defined Border classes are listed below.
 
 
 

 Border class

 Description

 AbstractBorder

 A base class that implements an empty border with
 no
size which is extended by many border subclasses.

 BevelBorder

 A three dimensional border that gives a raised or
 sunken
appearance. 

 CompoundBorder

 Two borders, one nested inside the other.

 EmptyBorder

 The empty border is not painted and as such is not visible.
 It replaces AWT Insets for adding space around a component. 

 EtchedBorder

 This border portray an etched surface. Two color objects
 may be supplied to represent highlights and shadows. 

 LineBorder

 A line border with a thickness that may be specified to the
 constructor. One form of the constructor takes a boolean to
 indicate the corners should be rounded. 

 SoftBevelBorder

 Creates a border with a raised or lowed bevel with
 softened
corners. 

 TitledBorder 

 A border that permits titles to be combined with the
 borders
in different ways, controlled by titlePosition
 and
titleJustification parameters. 

 Matte Border
  Paints a solid color or tiles an image in the border margin


//  EmptyBorder to adding Space around a component



Creating Borders By Instantiating the Border Classes


The examples below show a different approach where Border
classes are instantiated and applied to JButton components.


Border Examples


MatteBorder Example  
        Icon ike=new ImageIcon("images/PLAY1.jpg");
                                            JButton b1=new JButton("PLAY");
                                             b1.setBorder( new MatteBorder( 5 , 15 , 5 , 15 , ike) );

                                             //  insets top, left, bottom, right and a tile icon

EtchedBorder Example        JButton b2=new JButton(" Next ");
                                            b2.setBorder( new EtchedBorder(Color.white, Color.gray) );

                                            // highlight and shadow colors

LineBorderExample            JButton b3=new JButton(" Next ");
                                            b3.setForeground(Color.red);
                                            b3.setBorder( new LineBorder(new Color(250,240,230), 2, true) );

                                            // constructor that takes color, thickness, and rounded corners

SoftBevelBorder Example   JButton b4=new JButton(" Next ");
                                            b4.setForeground(Color.magenta);
                                            b4.setBorder(new SoftBevelBorder(SoftBevelBorder.RAISED,
                                            new Color(200,100,50), new Color(200,55,77)));
                                            // bevel type, highlight and shadow colors


TitledBorder Example 
         JButton b5=new JButton();
                                             b5.setForeground(Color.white);
                                             b5.setBorder(
                                             new TitledBorder(new LineBorder(Color.yellow),
                                             "SKIP"));

                                          // This shows the default arrangement. Constants can be
                                          // added to relocate the position of the text in the line


The following applet demonstrates these border variations.
Note that Matte was left out. This is because of security
restrictions at the college where Applets are restricted from
reading outside files. Here it would be a jpg file. ( Try Matte
at home where It should work fine. Also , if at the school
you can also import an image file and run the applet locally. )

//  There are techniques for downloading the applet and image in a Jar file
// so the image is not treated as remote
which should get around the firewall.

Applet Demonstrating Border Variations
 


Common Components



JLabel

The first component we look at is JLabel. JLabel allows
a developer to label the various parts of a GUI. ( In AWT,
the counterpart was called by the simpler name, 'Label'.)

Swing goes beyond AWT in permitting the miniature pictures
called icons to be added to components like label. This
allows the possibility of using images rather than words to
indicate a control's function. (Think of the arrows on a DVD
player.) Swing allows text and icons to be positioned in
different locations relative to each other inside a component. 

There is not a lot more to be said about JLabel, but we
can use JLabel as an example to discuss adding icons. It
is appropriate to do this early in the talk as what applies
to JLabel also applies to the other Swing components, all
of which also can have icons applied.

// set icons via the constructor or using the setIcon( ) method

Icon Setting and Positioning

Icons may be added via a components constructor or after
construction using the component's method, setIcon( ).
The default locations of the icons and text can be changed
using positioning methods discussed below. In the table
below, the constructors of JLabel are shown in their different
overloaded forms. These variations can be used to add and
position text and icons in a label.

// JLabel's background is transparent by default


Swing's JLabel is Transparent

Also if you had trouble setting the background color of the JLabel
this is because of a little advertised fact that it has a transparency
factor that by default is set to transparent. (AWT's Label class
wasn't transparent. You would set background color to match the
GUI.)

Transparency is a good idea for labels as typically you don't want
to see the label's rectangle. To change a JLabel's background so
that a background color setting is visible, call it's method,
setOpaque( boolean) and set it's boolean argument to true.


Example
 
 

JLabel label=new
JLabel("JLabel's background is transparent by default");
label.setOpaque(true);
label.setBackground(new Color(77,99,133));


JLabel Constructors

 

JLabel() 

 Creates a JLabel object without image or title.

 JLabel(Icon image) 

 Creates a JLabel object with an icon.

 JLabel  (Icon image, 
 int horizontalAlignment)

 Creates a JLabel object with an image and 
 horizontal alignment.

 JLabel(String text) 

 Creates a JLabel object with text.

JLabel(String text, Icon icon,
int  horizontalAlignment) 

 Creates a JLabel instance with text,
 image,
and horizontal alignment.

 JLabel  (String text,
 int horizontalAlignment)

 Creates a JLabel instance with the
 text and 
horizontal alignment.


In the following example, the layout is set to a grid layout. We will see
later this forces the label to occupy the whole area of the panel. This
was done just to increase the area that the JLabel occupied so the
effects of positioning could be observed. JLabel.RIGHT constant
moves both the icon and text as a group to the right margin of the
label.  ( You will have to supply your own JPG  file. )
 

Example

// reminder to include imports

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

        class Pic extends JPanel{
             Pic( ){
             setLayout(new GridLayout(1,1));
             Icon goPix = new ImageIcon("balloon.jpg");
             JLabel label=new JLabel("Balloon", goPix, JLabel.RIGHT );
             add(label);
             }

// this code needs a  main( ) method to run

The Magelang Institute's Swing tutorial on the Sun site uses
a nice technique of building examples inside JPanel extension
classes as in the example above. These panels then can easily
be instantiated in a Frame class like in the following example.
 

Example 

 class JTour extends JFrame{
    JTour( ){
       Pic p=new Pic( );

// getContentPane(). setLayout(new FlowLayout());
// use to add more then one display element at a time

       getContentPane( ).add(p);
       setSize(400,300);
       setVisible(true);
      setDefaultCloseOperation(EXIT_ON_CLOSE);
       }
 
public static void main(String [] args){
 new JTour( );
 }
}


Positioning Methods

The positioning methods take constants that are statically
defined in a repository
called the SwingConstants class.
The methods used for positioning in the horizontal
take LEFT,
 RIGHT and CENTER with CENTER being the default  value.
The
methods used for vertical positioning take the constants
TOP BOTTOM or
CENTER with CENTER being default.
These constants are referenced via the
class name using
the dot operator.

Example         

SwingConstants.BOTTOM
 

The setHorizontalAlignment( ) & setVerticalAlignment( ) Methods

These methods set the contents as a group, whether icon, text
or both, to the left center or right in the horizontal and to the top,
center or bottom in the vertical in the space that is defined by the
label. Notice, in some conditions setting these values will not
have an effect as the contents are already occupying all the
space that is available in the component and there is no where
to go. This will happen with text and icons in labels that have
been added to a flow layout where components are allowed to
occupy a minimal, preferred size.

// sets the position of the group within component can't observe the effect
// if the space or layout policy won't permit it


The setVerticalTextPosition( ) & setHorizontalTextPosition( ) Methods

These methods set the text position relative to the Icon. By combining
the constants
in the horizontal and vertical the text can be put in 9
positions relative to the icon.
At the top above the image, left right
and center. In the center, left, right and center
where the text is
centered on the icon and at the bottom, underneath the image, left,

right and center.

// sets text relative to icon
// for the assignment below just use these methods

The following code shows both sets of methods. The alignment
methods that set the whole group have a an alternate set of lines
commented out. If you change which lines are commented, you will
see the whole groups moment is controlled by these methods. The
relative position of text and icon though remain the same.


Example

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;


class PicDemo{

  PicDemo(){
   JFrame frame = new JFrame();
   Pic pic = new Pic();
   Container content = frame.getContentPane();
   content.add(pic);
   frame.setSize(900,900);
   frame.setVisible(true);
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

   }

public static void main(String[] args){
new PicDemo();
}
}

 class Pic extends JPanel{
             Icon goPix;
             JLabel label;
             Pic( ){
         goPix = new ImageIcon("sword_of_Orion.jpg");
             setLayout(new GridLayout(1,1));
         label=new JLabel("Balloon",goPix,JLabel.CENTER );
             
         // 1. sets the group position  

         label.setVerticalAlignment(SwingConstants.TOP);
         label.setHorizontalAlignment(SwingConstants.LEFT);
         
         //label.setVerticalAlignment(SwingConstants.BOTTOM);
         //label.setHorizontalAlignment(SwingConstants.RIGHT);
            
         // 2. sets text relative to icon      
 
         label.setHorizontalTextPosition(SwingConstants.CENTER );
             label.setVerticalTextPosition(SwingConstants.BOTTOM );
             add(label);          
         }
    }


JPanel  // implements double buffering, flow layout by default

Another simple and widely used component is JPanel. It is
an all-purpose sub-container to build sub-sections for GUIs. 
It supports double buffering which improves the quality of
painting operations that might occur on it's surfaces.

JPanels constructors allow specifying whether the double
buffering feature is turned on and which layout manager the
JPanel will use.  ( Double buffering is used for smooth image
display.)

// a JPanel depends on a container to be shown on screen

JPanel Aspects

By default JPanel has a flow layout. You might have expected it
to be grouped with the Container components but it really is in
it's own inheritance branch, being a sub-class of JComponent.
It is not like the major container components as it cannot be
realized on the screen without first being added to a base
container like JFrame.

// can't appear on it's own


JPanel Hierarchy

java.lang.Object
   |
  +--java.awt.Component
         |
        +--java.awt.Container
               |
              +--javax.swing.JComponent
                     |
                    +--javax.swing.JPanel  



JSeparator 
// a speciality component usually used with menus

JSeparator is typically used to add a spacer bar between
elements of menus and probably more is more aptly placed
with that topic. On the other hand it is an accessory component
that can be used just about anywhere.  In menus and toolbars,
the separator can be added with the addSeparator( ) method.
To add in other locations a JSeparator object is instantiated.

Example Showing a Non-typical Use of JSeparator

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class Separator{
public static void main(String[]args){
JFrame frame = new JFrame();


JPanel pan=new JPanel();
pan.setLayout(new GridLayout(3,1));
JLabel over =new JLabel("Over Separator");
pan.add(over);
JSeparator s=new JSeparator(SwingConstants.HORIZONTAL );
pan.add(s);
frame.getContentPane().add(pan);
frame.setSize(450,150);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

 


The Container Classes



Swing Containers Build On AWT Counterparts

Container classes are like the foundation in a building.
Everything is built on them. Given that neither the simplest
or most complex GUI can be presented on screen without
one of these container types, it is an a very important set
of classes to look at. 

The Container component are subclasses of AWT and
as such are called heavy-weight, peer-based and opaque
components. The container classes are heavy-weight in
that they use the native resources of the operating system
to render themselves visually on screen.

The four component, JFrame, JDialog, JWindow, and
JApplet are the only heavyweight containers in the Swing
library. Other JComponents are painted on the surface of
these components and don't need to make appeals to
native counterparts for their existence. For this reason,
the other JComponents are called light-weight
components.


The Four Heavy Weight Components of the Swing Package


Look at the Container Hierarchy and it is evident that heavy-
weight components are directly subclassed from AWT's
Window class. JWindow descends from Window. JFrame
descends from Frame which in turn descends from Window.
The other type of heavyweight components described in
the tree are the JDialog and FileDialog classes.

An Applet is also a container class. However, it has a unique
place in the component hierarchy, (probably due to it's early
invention in the history of Java.) Applet and JApplet are quite
unique and are treated as separate topics.
 
The fact that these heavyweight components are based on
AWT components is one of a number of reasons that we
should think of Swing as 'building on' rather than replacing
AWT.

The Swing Container Component Hierarchy Depends on AWT

    Object
         |
Component
         |
 Container
         |
  Window
         |
         |____JWindow
         |
         |____ Frame
         |              |____ JFrame
         |
         |____Dialog
                         |___JDialog
                         |___FileDialog

 

Applet Hierarchy     

Object
|
Component
|
Container
|
Panel
|
Applet
|
JApplet


// Component, Container and Panel are in the java.awt package,
// Applet is in java.applet, and JApplet is in javax.swing



JFrame



Differences Between Frames

If you instantiate JWindow the first thing you will notice it
doesn't have a top bar that permits adding an external
label to the frame nor does it have controls to close,
shrink or iconify the window. AWT's Frame is a descendant
of Window and adds these specialized features. Keep in
mind that you may wish to use the uncluttered look of
Window and JWindow to do more graphically oriented
presentations.

// JFrame extends Window and adds  label bar and
// closing & iconifying controls

JFrame goes on to differentiate from AWT's Frame class
by providing a sophisticated layered structure made up
of different container objects that enable features like
drag and drop, tooltips and pop-up menus to be added.


Two JFrame Variations  

JFrame variations are the practical beginning of building
GUIs that run at the command line. JFrame is the common
base window that Java uses to build GUIs. It can be used
in a variety of ways. 

In the following example JFrame is instantiated inside a
regular Java class.
 

Example of a Frame Created using Composition

import javax.swing.*;
import java.awt.*;

public class FrameTester {
      public static void main (String args[]) {
             JFrame f = new JFrame ("A Frame Created Inside a Class");
             Container c = f.getContentPane( ); 
             c.add (new JLabel ("A Label in a Frame "));
              f.setSize (300, 70);
             f.setVisible(true);
                   }
              }

In the above example there is no constructor and everything
is done inside
main(  ). A constructor could have been used
like the following example.

In the next example a JFrame class is created as an extension
of JFrame.


Example of a Frame Creation Based on Inheritance

import javax.swing.*;
import java.awt.*;

 public class FrameTester extends JFrame {
                       FrameTester(String s ){
                          // call to super to invoke label handling constructor

                          super(s);
                          JLabel jl= new JLabel(" A class extending JFrame");
                         getContentPane( ).add (jl);
                         setSize(300,70);
                         setVisible(true);
                         }
                      public static void main (String args[]) {
                         new FrameTester("A class extending JFrame" );
                         }
                  }

Base Requirements

While each of these examples have different features, both show
that JFrame requires having it's size set and must be made visible,
using the setSize( ) and setVisible( ) methods. The setVisible( ) can
be replaced with the older show( ) method.


 Have to Have Methods

// replace deprecated show( ) method


The Deprecated show( ) Method

The show( ) method of Component class was deprecated a long
time ago ( JDK1.1 ) but it still alive and well. Being deprecated is
never fatal it seems. Deprecation is like a sentence that is infinitely
commuted!

The Java designers would rather you use the setVisible( ) method,
using the JavaBean 'get / set' form that treats visibility as a property
and clearly describes what the method is doing.

// show( ) and hide( ) has been replaced by setVisible( ) 

Both examples show the getContentPane( ) method being used.
In one case a the ContentPane object is returned to a Container
reference and in the other case the add call is made right off the
getContentPane( ) method.

Notice as well in the example with the Constructor, the constructor
form of super( )
is called to invoke the parent's constructor of the
form that takes a String to label
the top bar of the frame.

A final point to observe, notice methods in the constructor are not
prefixed with
a reference. The reference that is implicitly supplied
is this.

Example   

this.getContentPane( ).add(component);


Summary of Key Features Using JFrame


JFrame Structure

With old AWT's Frame a call to getContentPane( ) was
not necessary as there was no ContentPane to call. With
JFrame, for a long time this call was
necessary as the
internal composition of the newer JFrame is composed of
several
sub-components. The same is true for the other
heavyweight components. The four heavy weight
components,
JFrame, JApplet, JWindow and JDialog along with a fifth
component, JInternalFrame
all implement the
RootPaneContainer interface.

The result is each of these components have a set of
methods that return the different panes associated
with
JRootPane. (i.e getContentPane( )  returns the content
pane, getGlassPane
( )  returns the glass pane. )

New in JDK 1.5, 'Old Habits Die Hard'

It seems that old habits die hard, and in JDK 1.5 plain add( )
was revived, in a form that hides the call to getContentPane( ).

Example

getContentPane( ).add (jl);

// becomes just

add(jl);

It is probably good form to retain the call to getContentPane( )
to  communicate clearly the component that is being called.


JRootPane
 
// lower-case i.e. glassPane, used in J2SDK docs 

Following is a diagram of the hierarchical arrangement of
JRootPane.

Diagram of the JRootPane Hierarchy

JRootPane
        |___glassPane
        |___layeredPane
                       |___jmenubar [ optional ]
                       |___contentPane


The glassPane is transparent and as such is not visible.
It is located on top of everything, where it can intercept
mouse events in association with actions like displaying
tooltips.

The menubar is an optional component. If added it will appear
at the top edge of the frame. Notice because it has it's own
place in the root pane structure a call to getContentPane(  )
is not necessary to add a menubar. We see later menubars
are set using the setMenuBar( ) method.

For a time any child classes added to the structure would
be added via the content pane with add methods. Now the
following examples may be simplified as was shown above.


Example   
  

getContentPane( ).add(child_component);

// the same is true for adding layout managers
.

Example   

getContentPane().setLayout(new GridLayout( 3, 2));
 

JLayeredPane  // layers details primarily for reference

It is early in the course to worry about layers. For the now we
just survey some of it's architectural features so what possibilities
there are become apparent. 

JLayeredPane is the parent class of all children in the JRootPane
other than it's sibling, glassPane. The class allows components
to be located at different depths in the container by placing them
in different layers. 

JLayeredPane Constants are Stored as Integer Wrapper Objects

The default layer is represented by the constant value,
JLayeredPane.DEFAULT_LAYER. Unlike other constants,
these layers are referenced via static instances of the
Integer wrapper class. This is a nice example of the use
of wrapper classes in use. 

JMenuBar and the contentPane are each added to the
JLayeredPane object at the layer represented by the
JLayeredPane.FRAME_CONTENT_LAYER constant.
This capability is used to allow menu pop-ups, dialog
boxes, and dragging and dropping to occur at appropriate
visual layers.

The set of convenience layers defined by by the following
table of constants, each representing a static Integer object.
(If you print to console one of these constants the toString( )
method is automatically called and the contents of the
wrapper class is rendered to screen.)
 
 

DEFAULT_LAYER 

 The standard bottom-most layer where most
 components  go.         // Equivalent to new Integer( 0 ).

PALETTE_LAYER 

 Next up from the default layer, a good location for floating
 toolbars or palettes, positioned above other components.
                               // Equivalent to  new Integer(100).

MODAL_LAYER 

 Anything in this layer appears over items in the palette
 layer. This layer is used for modal dialogs.

                               // Equivalent to new Integer(200)

POPUP_LAYER 

 Displaying above the modal layer, the pop up layer paints
 over items in the dialog layer. This allows pop-ups that add 
 help contexts and choice boxes to supplement dialog box
 activity.                   // Equivalent to new Integer(300).

DRAG_LAYER 

 A dragged item is assigned to the drag layer, the top layers
 defined in JLayeredPane, and then reassigned to the layer
 it originated from.     // Equivalent to new Integer(400).


// JLayeredPane.FRAME_CONTENT_LAYER has a value of -30000.
// Seems the designers really want to leave some room for layers!
// this is counting by 100s so that leaves room for 300 sub-layers.


JLayeredPane Methods // add components to layers

JLayeredPane manages it's set of components like other containers
with the added feature of allowing layers to be defined within itself.
Components in higher layers are painted over objects placed in
lower layers. Each layer is represented by a distinct integer. This
number can be passed in to an add method via the Integer wrapper
class to set the layer an object will be added to. Java documentation
shows the following two examples.


Example   

layeredPaneObject.add(labelObject, JLayeredPane.PALETTE_LAYER);


The Integer wrapper class can be used to create an equivalent
expression.


Example

JLabel label=new JLabel("layered label");
JLayeredPane pane=this.getLayeredPane( );
pane.add(label, new Integer(100));


JLayeredPane also has methods to reposition a component inside
it's layer and to set the layer or the layer and position of a component.


Layering  Example

A complicated but interesting demonstration of layers can be
found at the following site. This demo uses a loop to set up
layers at different levels. The layout layers are each designated
with graphics entered using the setBounds( ) methods. Then
an image takes it's cue from listings in a combo box to decide
which layer to show up under. This example is ahead of where
we are as it uses event handling. Interesting is the use of a
MouseMotion Listener that is inlined as an anonymous inner
class.

Layering Example

http://www.lkn.ei.tum.de/arbeiten/faq/man/JAVA-tutorial/ui/swingComponents/layeredpane.html


Close Operations    // as of JDK ~ 1.4.x

JFrame defines a setDefaultCloseOperation( ) method. Supplying
constants defined in the WindowsConstants class will cause the
Frame to do nothing on when the close button is clicked, to hide
the frame when the button is activated or to hide and dispose the
frame.

These constants are

The first three constants do not cause the application to exit and
close the command line session. EXIT_ON_CLOSE will close
the dispose of the Window and close the DOS session.


The New Effective Way to Close a Frame // as of ~JDK 1.4

Example    // inside a JFrame constructor

setDefaultCloseOperation(EXIT_ON_CLOSE); 

Notice this example presumes you are in a JFrame constructor.
If you build a frame outside a constructor via an instantiation the
form will be something like the following example.


Example

frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

As a practice using the second form where the constant
is referenced off of the class name will work in all situations,
inside a constructor or out.

 
// Something you don't have to worry about. In earlier versions of Java,
// pre- 1.4, DISPOSE_ON_CLOSE
would hide and free resources associated
// with visual components but would not close the
System process. (The
// command line remained running.) This required an additional call

// System.exit( ) in a windowClosed( ) method. Fortunately, setDefaultCloseOperation( )
// closes everything out so we no longer have to be concerned about this issue.



Self Test                                                      Self Test With Answers



1) Which of following features was not only a Swing feature but also available in AWT.

a) add icons
b) set tooltips
c) change layout managers
d) layer pop-up menus

2) Like Icon, the Border interface has three methods. Which of the following is not a
    Border interface method.

a) getBorderInsets( )
b) isBorderOpaque( )
c) setBorderInsets( )
d) paintBorder ( )

3) Pick the incorrect statement?

a ) Borders can be customized by extending AbstractBorder
b) JComponent provides the setBorder method
c) Swing defines six preset border classes.
d) JComponent implements the Border interface
 

4 ) Select the incorrect statement regarding JLabel.

a) An icon can be set in a JLabel using setIcon( ).
b) The background of a label by default is transparent.
c) Set methods can be used to position text relative to icon in 6 different ways.
d) horizontal and vertical alignment methods can set the relative position of the
    text and icon as a group.
 

5) Which of the following statements is not true regarding JPanel?
a) JPanel's default layout manager is flow layout.
b) Like JFrame,  JPanel can be made visible to screen without
    being added to another container.
c) JPanel descends directly from  JComponent.
d) JPanel supports double buffering?


6 )  Only one of the following components is considered heavyweight? Which is it?

a) JPanel
b) JComponent
c) JDialog
d) JLabel


7) True or False.

If AWT and Swing Components are mixed  in the same GUI a compiler error results.  _____


8) True or False

Peer-based means a corresponding component is built on the underlying system  ____
 



Exercise



1) Create a panel inside a JFrame.

2) Set the panel's layout to a 3 by 3 grid.

// We cover layout managers separately. For now modify
// this line found in the code sample in the note to the
// following form

Example

setLayout(new GridLayout(3,3));

3) Find an image on the web that can be iconified. Using 
the methods,
setVerticalTextPosition( ) and
setHorizontalTextPosition( ) methods
create 9 labels with
the icon and text. Show all the ways that text can
be
positioned relative to the icon.


// get rid of the alignment methods in the example in the note

// these are not involved with this exercise


4) Add a tooltip for each label indicating the positioning
strategy adopted
in each label.

5) Use the  setDefaultCloseOperation(EXIT_ON_CLOSE)
method to
provide a closing mechanism for the frame.

6) Change the borders on the components to two different
border variations. In one case use BorderFactory methods.
In the second case use an instantiation of a Border class.