Text Components
& Layout Managers


Peter Komisar      ©      Conestoga College     latest version: 5.8  2010



As with other types of Swing components, Java's text
components may be used in a simple manner for fast
and easy deployment or in a more sophisticated fashion
that takes advantage of the underlying Model View
Controller architecture. In this part of the note, we take
a short tour of the most used text components followed
by a survey of the models that are at the heart of the
text component architecture.

// recall model represents data, view is the visual presentation
// and controller takes view input and applies changes to the data


JTextComponent

JTextComponent is the generalized parent class for a
set of text-based Swing components. JTextComponent
defines methods commonly used in basic text editors,
methods such as copy( ), cut( ) & paste ( ), getText( ) and
setText( ). JTextComponent supplies these and other
methods to it's subclasses. Following is the hierarchy
of the text components.
 

The JTextComponent Hierarchy   

     Object
       |
   Component
       |
   Container
       |
  JComponent
       |
 JTextComponent
       |
       |___ JTextField
       |        |___JPassword
       |
       |___ JTextArea
       |
       |___ JEditorPane
       |___ JTextPane
 


JavaBean Property Sets

JComponents have a set of properties that are accessible
through getXXX and setXXX( )  methods. This is part of
the JavaBean design that all Swing and AWT components
adhere to. For instance for JTextArea, properties such as
'document', 'margin', 'caret', 'highlighter',  'keymap',
'caretColor', 'selectionColor', 'selectedTextColor', 
'disabledTextColor'  and 'editable' may be set or selected.  

JTextField, JTextArea and JEditorPane are the well-used
subclasses of JTextComponent. JPasswordField is an
extension of JTextField and and JTextPane is an extension
of JEditorPane. To make large sections of text viewable
the simplest approach is to add the text area to a
JScrollPane.

In the following example, explore the controls for changing
blink rate and whether a component is editable.

Code Demonstrating Getting & Setting JTextArea Properties

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

class TAProperty extends JFrame{
      TAProperty(){
      JTextArea jta=new JTextArea();
      this.getContentPane().add(jta);
      this.setSize(600,300);
      this.setVisible(true);
      this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    
// 'document', 'margin', 'caret', 'highlighter', 'keymap', 'caretColor',
// 'selectionColor', 'selectedTextColor',
'disabledTextColor' & 'editable'
     
       jta.setText("\nSelected JTextArea Properties");
       jta.append("\n______________________________\n\n");
       Document document = jta.getDocument();
       jta.append("Document type: " + document + "\n");
       boolean editable = jta.isEditable();
       jta.append("Is editable: " + editable + " \n");
       //  jta.setEditable(true);
       editable = jta.isEditable( );
       jta.append("Reset editable property: " + editable + " \n");
       Insets insets = jta.getMargin();
       jta.append("Margin insets: " + insets  + "\n");
       Caret caret = jta.getCaret( );
       caret.setVisible(true);
       jta.append("Caret description: " + caret  + "\n");
       jta.append("Caret Blink Rate:  " + caret.getBlinkRate() + "\n");
       //  comment in to reset blink rate observe the change
       caret.setBlinkRate(200);
       jta.append("Caret Blink Rate (after reset) : " + caret.getBlinkRate());
       }
    
       public static void main(String[]args){
        new TAProperty( );
        }
    }     

  

JTextField   // supports a single line of text

One important point to note with text components is that
setting column widths correlates to number
of field characters
directly only for fonts with fixed
widths, for example where an
' i ' takes the same
space as a 'w'.

// column widths relate to fixed fonts

JTextField is the component designed to accept a single line
of character data. JTextField supports setting of text justification
with setHorizontalAlignment( ). The three available settings are
LEFT, CENTER,  and RIGHT, where LEFT is the default.


Example

JTextField textfield = new JTextField( );

Following are JTextField's constructors.

JTextField Constructors

//  a JTextField based on model, text & columns

// an empty JTextField with given number of columns.

// a new TextField initialized with specified text.

// a new TextField initialized with specified text & columns.
 

JTextArea // text field taken to two dimensions

JTextArea, compared to JTextField, has the enhanced
ability to allow multiple lines of text to be entered and
displayed in it's viewable area. It generally would be
used for any text entry or display that would require
more than a single line.

JTextArea has a range of constructors, from a minimal,
'no args' constructor to one that allows specifying some
initial text and the number of rows and columns that will
be shown. Like other components,  how JTextArea is
displayed will be influenced by the type of layout manager
that is being used control layouts. This sometimes leads
to row and column setting being 'over-ruled' by the layout
policy.

// at times settings seem to be 'broken' when actually the layout
// manager is overruling the user's settings

Useful JTextArea Methods

JTextArea has a method, setLineWrap( ) that will cause
a line to wrap instead of continuing into an 'out-of-range'
area of the component. It also has a method that will
disallow a word from being broken at a syllable. If the
argument to setWrapStyleWord( ) is set to 'true', the
lines will be wrapped at word boundaries. These two
useful methods are shown in the example below.


Useful JTextArea Methods


Example   
 

JTextArea textArea=new JTextArea(" Comments ", 10, 30 );
textArea.setLineWrap( true);
textArea.setWrapStyleWord( true);


JTextArea Constructors

Following is a brief summary of JTextArea( ) constructors.

// constructs a new TextArea.

// a new JTextArea with specified document model

// a new JTextArea with model, text, rows & columns

// a new empty TextArea with specified # of rows & columns.

// constructs a new TextArea with the specified text

// a new TextArea with the specified text, # of rows & columns.
 

JPasswordField

JPasswordField is a specialization of JTextField. It masks
characters entered into it by echoing to the field either an
asterisk or a user defined character. The setEchoChar( )
method can be used to set the character that is echoed in
the password field.

Example    

JPasswordField password = new JPasswordField(20);
password.setEchoChar ('^'); 

Following is a code sample that shows these three
components.


Code Sample

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

class Text{
     JTextField field;
     JTextArea textArea;
     JPasswordField password;
     JPanel panel;
    public Text() {
    JFrame frame = new JFrame();
    Container content=frame.getContentPane( );
    panel = new JPanel();
    field =new JTextField("A text field");
    password = new JPasswordField(20);
    password.setEchoChar ('^');
    textArea =new JTextArea("A Text Area");
    panel.add(field);
    panel.add(password);
    panel.add(textArea);
    content.add(panel);
    frame.setSize(200,300);
    frame.setVisible(true);
     }

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


JEditorPane

The JEditorPane class is a specialization of the parent
JTextComponent. It is designed to render pages in HTML
or RTF formats. Links can be processed with the aid of
the HyperlinkListener interface. Pages are loaded into the
editor pane using the setPage( ) method.

// HyperlinkListener is an example of a listener class. Listeners are
// participants in
Java's model for event processing. We cover
// listeners in the Events note.


The following code sample is pretty primitive. If the URL is
not available no alternative output is provided. JEditorPane
is slow and somewhat unforgiving in how it interprets page
layouts. Still it could be very useful in dedicated applications
to provide basic interpretation of HTML pages that have been
designed to suit the component's capabilities.


Code Sample

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

class Browser extends JFrame implements HyperlinkListener{

         Browser(){
         
         JEditorPane editorPane = new JEditorPane( );
         editorPane.setEditable(false);
         JScrollPane scroll = new JScrollPane(editorPane);
         getContentPane().add(scroll);
          URL url=null;
          try {
               url=new URL( "http://www.nytimes.com//" );
               editorPane.setPage(url);
              }
              catch (MalformedURLException mue){
              System.err.println( " incorrect url formatting ");
              }
              catch (IOException e) {
             System.err.println("Attempted to read a bad URL: " + url);
              }
              
              setSize(800,600);
              setVisible(true);
              }
         public static void main(String[]args){
           new Browser();
           }
       // HyperlinkListener method as a stub
          public void hyperlinkUpdate(HyperlinkEvent he){ }
        }
 

JTextPane

JTextPane descends from JEditorPane. A nice feature
of JTextPane is the ability to add style to a document
using a set of attributes. A default attribute set is available
in the form of the SimpleAttributeSet. Different attribute
style settings are collected in the SimpleAttributeSet
object. They are set using a set of static style methods
in the StyleConstants class. JTextPane is a full-featured
text editor that supports formatted text, word wrap, and
image display.

// You may wish to comment out the styling code
// to see the before after effect
 

Example

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


class JPane {
   JFrame jf;
     Icon icon;
     JTextPane jt;
    JPane( ){
         jf=new JFrame( );
         jt= new JTextPane();
         jt.setText("The Page");
         MutableAttributeSet attr = new SimpleAttributeSet( );
         //  ImageIcon icon = new ImageIcon("E3.jpg");
         // StyleConstants.setIcon(attr,icon);
         StyleConstants.setItalic(attr, true);
         StyleConstants.setFontSize(attr, 18);
         StyleConstants.setFontFamily(attr, "SansSerif");
         StyleConstants.setForeground(attr, Color.blue);
        
         jt.setCharacterAttributes(attr, true);
        jt.setText("The Page text is replaced and formatted");       
// the boolean dictates if a previous set should be replaced
         JScrollPane js=new JScrollPane(jt);
         jf.getContentPane().add(js);
         jf.setSize(800,600);
         jf.setVisible(true);
      }
 public static void main(String[]args){
       new JPane( );
      }
 }


JScrollPane



While AWT automatically adds scrollpanes as needed to
components, Swing requires you to add scrollpanes as they
are needed. There are different approaches available to
supplying scrolling for visual components.  For instance, a
scrollbar can be added to a component using the JScrollBar
class which we look at separately in a later note.


Two Approaches to Using JScrollPane
 

Using JScrollPane

In Swing, scrollbars that are added to components, only
appear on an 'as needed' basis. For instance, scrollbars
will only appear when the viewing area available on a text
component is exceeded.

The most convenient way to make a component scrollable
is to add the component object to a JScrollPane object.
There are two ways this can be done.

The easiest is the create a component and pass it to
the constructor of the JScrollPane( ).

Example       

JTextArea textObject=new JTextArea("Text");
JScrollPane pane = new JScrollPane(textObject);


Using JViewport

The JViewport component can be thought of as viewable
part of a scrollable
component JViewPort is used inside
text components to handle text scrolling.
You can get a
handle to the JScrollPane's viewport with the getViewport( )

method. JViewport uses Swing's ChangeListener to
process events.

The other approach is to access the particular component
that represents the viewable area of the ScrollPane called
the JViewport. JScrollPane provides a getViewport( )
method to get a handle to this component. Then the
component is added to the JViewport object.

Example       

JViewport viewPort = pane.getViewport( );
viewPort.add(textObject);

The following code shows the easier way and also
demonstrates that not just text components can be
scrolled.

Example

public class ScrollFrame5 extends JFrame {

         public ScrollFrame5(String s ) {
               super(s);
               Icon marsIcon = new ImageIcon("balloon.jpg");
               JLabel mars= new JLabel(marsIcon);
               JScrollPane scrollPane =   new JScrollPane(mars);
              getContentPane( ).add(scrollPane, BorderLayout.CENTER);
              setSize(140,200);
              setVisible(true);
           }
       public static void main(String[]args){
              new ScrollFrame5("Map of Mars");
              }
    }

To Remember When Processing ScrollBar Events

There is a bit of obscurity that needs to be overcome when
adding action processing code to JScrollPane that isn't
present when using separate JScrollBars. JScrollPane
itself doesn't support AdjustmentListener. You need to use
the methods, getHorizontalScrollBar( )  and or
getVerticalScrollBar( ) to get a handle to the scroll bars
objects and then add your adjustment  listeners to them.
 
// we cover event processing later

   


Models Used in Text Components



Before moving onto Layout Managers we consider the
underlying architecture of text components. Don't worry
about the details here. This is just a general overview of
how the 'pieces of puzzle' fit together.

The Java text components use a MVC or Model View
Controller architecture. The model used in Swing text
components is an implementation of the Document interface.
The 'Controller' is represented by an implementation of
the abstract, EditorKit class. The 'View' is provided by
an object returned by the UIManager.

The Document Interface

// not to be confused with the Document Interface!

The Document interface found in the javax.swing.text
document has a custom model based on a tree data
structure useful for describing the hierarchical aspects
of a document.

There is also a Document Interface defined in the
org.w3c.dom package which is an implementation of
the W3C's XML Document model. This is an entirely
separate model from the one used in Swing.


The Java Document in the MVC Pattern

Java's Document Object serves as the 'model' in the
MVC architecture The 'document',
in Java, is a class
that implements the Document interface. The Document
interface
supplies a container for text for everything from
very simple
plain textfields to complex documents like
XML or HTML pages.

At it's simplest, a component's content, as described by
the document object, is a sequence of
Unicode characters
which starts at the offset 0.
  A range corresponding to
'Detroit' may be thought of as the space before and after
a set of characters. For Detroit the range is described as
0 - 7 . 

Example of a Range  // Detroit has the range 0 to 7 

 D  e  t  r  o  i  t      C  i  t  y
0  1  2  3  4  5  6  7   8  9  10 11 12

Abstract document defines methods such as getLength( ),
getText( int, int ) and getText(int,int,segment) to
access
groups of characters that makes up a document object's
content.

The following code just shows how the characters represented
in a text component are a view of the document model here a
text string that is the data behind the view.

Using a Few AbstractDocument Methods

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

class QDoc extends JFrame{
      QDoc(){
      JTextArea jta=new JTextArea( );
      this.getContentPane().add(jta);
       // this string becomes the document model
       jta.setText("\nHey Bill! How are you doing!");
       Document document = jta.getDocument( );
       jta.append("\n____________________________\n\n");
       jta.append("Document Length: " + document.getLength()+ "\n");
    try{
       jta.append("\nText at index 1 and length 8:   " +                      
       document.getText(1,8));
       // targeting ! mark
       jta.append("\nGetting the Explanation Mark: " +               
       document.getText(28,1));  
       }
    catch(BadLocationException ble)
       { System.out.println("Bad Location");
       }
     
      this.setSize(600,300);
      this.setVisible(true);
      this.setDefaultCloseOperation(EXIT_ON_CLOSE);           
      }
        public static void main(String[]args){
        new QDoc();
    }
    }


Element Objects
// the large parts of a hierarchical data structure

The document stores textual content in 'Element' objects.
A paragraph, for instance, 
may be represented as an
Element object.

An element is an object of a class that implements the
Element interface. The Element interface
contains methods
that describe how an object can be related to another in
the larger
document structure. The getDefaultRootElement( )
and getRootElements( ) provide
access to the elements of
a document's structure.

 

 An Example of a Document's Hierarchy of Element Object

                                 Course
                                /            \
                        Unit1             Unit2
                       /        \
          Section1           Section2
                                  /        \
                Paragraph1             Paragraph2


// where nodes are implementations of the Element interface

Adding and removing text is referred to as mutating the
document. Document mutation
is accomplished using
the methods of the Document interface, insertString( ),
remove( )
and createPosition( ).       

In addition to standard editing capabilities, the Swing
text components also supply 'undo' and 'redo' capability
and action processing based on caret changes.

References for further investigation

http://java.sun.com/products/jfc/tsc/articles/text/element_interface/ 

http://web.mit.edu/swing_v1.1/swing-1.1beta2/doc/api/com/sun/java/swing/text/Document.html


Document Implementations

Following is a description of the hierarchy and relationships
between the different Document classes and the interfaces
they implement.
The AbstractDocument class implements
Document. AbstractDocument is subclassed
to PlainDocument
and DefaultStyledDocument.

DefaultStyledDocument implements a Document sub-interface
called StyledDocument. HTMLDocument is a subclass of

DefaultStyledDocument. A diagram is the best way to show
these relationships.

Document Hierarchy


       Abstract Document
  implements Document
      _________|_________
     |                   |
PlainDocument   DefaultStyledDocument implements StyledDocument
                         |
                     HTMLDocument


The text components all have the simple PlainDocument for a
document model except
for JTextPane. JTextPane by default
has DefaultStyledDocument as it's document model.
Even the
JEditorPane has PlainDocument set as it's default model.

The document model used with a component can be changed
in a number of ways. If
the setPage( ) method is used with a
text component the document model may change
depending
on what the file format is of the page that is being set. The
document can also
be changed using the setDocument( )
method. The component's constructors can
also be used to
specify a particular Document type.



Layout Managers               
Peter Komisar 
©  Conestoga College



Early Problems With GUI Portability


AWT introduced Layout Managers to assist in laying out
components in GUIs. Layout managers avoid the use of
absolute values and adopt strategies that assist in porting
Java GUIs across platforms.  

Swing components, which are painted superficially on a
single native base component now make the use of an x, y
coordinate placement more viable as individual peer-based
components are not insisting on particle sizes. One downside
to using x, y coordinates to place components is that the
resizing behavior of layout managers is lost. If required
the programmer can supply this behavior.

Once a programmer is familiar with Java's layout managers,
almost any layout can be
created. It may be daunting at first
to get things exactly as you would like them
.
 

The three most common AWT layouts are:

The most versatile layout but hardest to use is:

Another layout in classic AWT is:
// CardLayout has effectively been supplanted by JTabbedPane component

There is nothing wrong with CardLayout. It's use is now
often
supplanted by the JTabbedPane component found
in the javax.swing
package.

GridBagLayout is purported to be the manager most often
used 'behind
the scenes' in commercial IDEs and visual
GUI builders. Swing introduces a number of new layouts
but these are custom designed and associated with single
Swing components. One new layout, BoxLayout is a useful
in addition for GUI design.

// a new general use Swing Layout Manager


No Layout & Custom LayoutManagers



Following are different layout strategies that can be taken
for laying out components. It use to be with AWT that using
a null layout was not recommended as creating an absolute
grid with peer-based components might create unpredictable
results when porting between platforms. 

Now with Swing's peerless components using a fixed grid
seems to be a viable approach, particularly if you do the
grid on a peerless component that you add to the peer-based
container.

No LayoutManager  

Using no layout is possible. No layout allows the use of
a grid which can be customized exactly as required. One
can use absolute coordinates to place components. In order
to disable any default layouts, the container's layout is set to
null creating the situation where no layout manager
is active.
This is done using the setLayout( ) method.


Example  
 

component.setLayout(null);


Nulling the Layout Allows setSize ( ) and setBounds( ) To Work

This will lead to calls like setSize( ) and setBounds( ) being
enabled and allowed to work. Normally these methods do not
function as they are overridden by
the layout managers. With
no layout, positioning
components is left to the programmer,
including any activity that is needed if the
container is re-sized.
This requires overriding the container's setBounds( ) method.

Normally only setBounds( ) is used as setSize( ) just calls
setBounds( ). Following is some code which shows a null
layout being used.

 

Null Layout Code Sample

class NoLayout extends JFrame{
  NoLayout(String s){
    super(s);
    JPanel panel=new JPanel();

// here's a panel's layout is set to null
    panel.setLayout(null);  
                      
 
    JLabel label= new JLabel("A Label");

// here is a component having it's bounds being set

    label.setBounds(40,20,120,20);    

    panel.add(label);
    JTextField text=new JTextField("A loaded textfield");
    text.setBounds(40,70,120,20);
    panel.add(text);
    JTextArea textArea=new JTextArea(" Some text \n in a text area");
    textArea.setBounds(40,120, 120, 50);
    panel.add(textArea);
    getContentPane().add(panel,BorderLayout.CENTER);
    setSize(250,250);
    setVisible(true);
    }
public static void main(String[]args){
    new NoLayout("A frame set to a null layout");
    }
  }

 // the convenience of a null layout is fine grained control of a layout.
// The downside
is this layout will not re-size. 
 

Creating Custom Layout Managers 

The common layout managers supplied by the Java
AWT API are implementationsof two interfaces:


You might experiment by creating your own custom
layout managers by implementing the five
methods
of
the LayoutManager interface or the ten methods
of the interface,
LayoutManager2.

For most of us, it will be more convenient to use stock
layout
managers or no layout managers at all.


Border, Flow & Grid Layout Managers



Overloaded add( ) Methods of  Container Class

All components inherit overloaded versions of the add( )
method, which will allow variations on how sub-components
are added to containers. Two of these add methods allows
specifying an index, which allows placing a component in
a particular compartment of a layout grid. The simpler of
the two is exampled below.

Example

add (Component comp, int index)

BorderLayout

A Border Layout divides a container's into five regions,
north, south, east, west, and center. Each region is
has
a corresponding constant, NORTH, SOUTH, EAST,
WEST, and CENTER.
When adding a component to a
container with a Border Layout, use one of these
five
constants as in the following example.

Example

    Panel p = new Panel();
    p.setLayout(new BorderLayout( ));
    p.add(new Button("Okay"), BorderLayout.SOUTH);

BorderLayout interprets the absence of a string specification
the same as the constant
CENTER.

Example

   Panel p2 = new Panel( );
    p2.setLayout(new BorderLayout());
    p2.add(new TextArea());  

// Same as p.add(new TextArea(), BorderLayout.CENTER);


BorderLayout Example

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

class f extends JFrame{
       f(){
        add(new Button("NORTH"),BorderLayout.NORTH);
        add(new Button("SOUTH"),BorderLayout.SOUTH);
        add(new Button("EAST"),BorderLayout.EAST);
        add(new Button("WEST"),BorderLayout.WEST);
        add(new Button("CENTER"),BorderLayout.CENTER);
        // center is the default add        
        setSize(800,600);
        setVisible(true);
        }
        public static void main(String[]args){
          new f( );
        }
        } 



Just For Reference

BorderLayout supports four relative positioning constants.
These four are BEFORE_FIRST_LINE, AFTER_LAST_LINE,
BEFORE_LINE_BEGINS, and AFTER_LINE_ENDS. In
a container
set to ComponentOrientation.LEFT_TO_RIGHT,
these constants
map to NORTH, SOUTH, WEST and EAST,
respectively.
Mixing the two types of constants can lead to
unpredictable results and should be avoided.

FlowLayout

A flow layout arranges components in a left-to-right flow,
top-to-bottom centering
as it goes. It works much like a text
editor that has been set to center text. Flow
layouts are often
used to arrange buttons in a panel. It will center buttons left
to
right until no more buttons fit on the same line. Each line
is centered. Flow layout
has three constructors that can be
used to effect alignment and inter-component
spacing.

Flow Layout provides the constants, CENTER, LEFT,
RIGHT,
LEADING and TRAILING, used  to control how
components are aligned. LEADING
will cause components
to line up with the component on the left above it.
Trailing
causes lining up to the right on the vertical axis.

Flow Layout Constants

The layouts use int values to add pixels of space between
the components in both the horizontal and vertical
directions.
Flow Layout will as much as is possible allow components
to retain
their preferred size and shape.

FlowLayout Constructors allow specifying alignment and
the gap between components. The default is 5 pixels in
both dimensions.


FlowLayout Constructors


FlowLayout can also use the overloaded version of the
add( ) method to insert a
component at a particular index
in the list of components being added.

Example     

flow.add(new JButton(" Inserted at 5 by offset 4 ") , 4 );

Following is a code sample that shows the FlowLayout
class in action.

FlowLayout Sample

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

class Ed3 extends JFrame{
         JButton j1,j2,j3,j4,j5,j6,j7,j8,j9;
    Ed3(){
        JPanel flow=new JPanel();

        flow.setLayout(new FlowLayout(FlowLayout.LEADING,10,20));      
        // try it with trailing to see the difference
        JButton[] buttons=new JButton[]

        { j1,j2,j3,j4,j5,j6,j7,j8,j9 };
        String[] names=
        {"One  ","Two  ","Three","Four ","Five ",
        "Six  ","Seven","Eight","Nine "};
        for(int i=0;i<9;i++){
        buttons[i] = new JButton(names[i]);
        buttons[i].setFont(new Font("Monospaced",Font.ITALIC|Font.BOLD,14));
        flow.add(buttons[i]);
        }

        getContentPane().add(flow);
        JLabel label=new JLabel("Flow Test");
        getContentPane().add(label, BorderLayout.NORTH);
        setSize(400,300);
        setVisible(true);
        }
        public static void main(String[]args){
        Ed3 ed=new Ed3( );
        }
        }
 

GridLayout 

// opposite to flowlayout with respect to preferred size

GridLayout is opposite to FlowLayout which respects
the preferred size of components. GridLayout causes
a component added to one of it's grid elements to fill
that element.

The GridLayout class is a layout manager that lays out
a container's components in a
rectangular grid. The
container is divided into equal-sized rectangles, and one
component
is placed in each rectangle. The number of
rows and columns can be specified as integers
to the
constructor or set with the methods setRows( ) and
setColumns( ) .

Example     

setLayout(new GridLayout(3,2));

//  sets the layout to a grid of three rows and  two columns.

If the number of rows and the number of columns have
not been specified, (using the
no-args constructor of
GridLayout) the layout creates enough columns to show
the
number of components that have been added. If the
row is specified then the required
number of columns is
calculated. The columns will also be adjusted even if
specified.
For example, if three rows and two columns
have been specified and nine components
are added to
the layout, then they will be displayed as three rows of
three columns.

Specifying the number of columns affects the layout only
when the number of rows is
set to zero.

// rows are fixed while columns vary


Card & GridBagLayout



CardLayout

The behavior of card layout has been supplanted by the
easy to use JTabbedPane
Swing component. JTabbedPane
is also recommended for changing screens inside a GUI.

CardLayout is available for your use and is your only
choice for this type of behavior
if restricted to AWT.
This might be the case in using Applets and maintaining
compatibility
with browser using older Java Development
Kits.

CardLayout treats each component in the container as a
card. Only one card is visible
at a time, and the container
acts as a stack of cards. The first component added to a

CardLayout object is the visible component when the
container is first displayed. The
ordering of cards is
determined by the container's own internal ordering of its
component
objects. CardLayout defines a set of methods
that allow an application to flip through
the cards in order,
or to show a specified card.

CardLayout's addLayoutComponent( ) method can be
used to associate a string identifier with a given card
for fast access.

// precursor of the layering behavior that was added to JFrame


GridBagLayout  // a 'dynamic' grid

GridGagLayout takes the idea behind the GridLayout
manager and adds variability to the size of each grid cell.
Where a grid layout is fixed to a uniform grid of rows and
columns, GridBagLayout allows different properties to
be added to each grid element so the elements can be
arranged in flexible asymmetrical patterns. The JDK
documentation refers to it as a 'dynamic' grid.

The properties used to effect how each cell of the grid is
presented is stored in a GridBagContraints class. The
following GridBagContraints constructor shows the properties
that the GridBagConstraint class contains. The lower case
fields can have a value assigned to them while those that
are all uppercase signal they are constants. The constraints
that can be assigned values can all be passed into the
second of GridBagConstraints constructors which is
shown below.


GridBagConstraints Constructors
 

public GridBagConstraints( )   
// The no-args versions sets all the constraints to default values

public GridBagConstraints
    (
    int gridx,         // the cell at the left of the component's display area
    int gridy,         // the cell at the top of the component's display area,
    int gridwidth,    // # of cells in a row for the component's display area.
    int gridheight,    // # of cells in a column for the component's display area.
    double weightx,   // specifies how to distribute extra horizontal space.
    double weighty,    // specifies how to distribute extra vertical space.
    int anchor,   // locates the  component when it is smaller than it's display area
    int fill,           // used to size a component to an area
    Insets insets,  // min space between the component & display area edges.
    int ipadx,     // specifies space to add to the minimum width of the component.
    int ipady    // specifies space to add to the minimum height of the component
   
  


GridBagConstraint Constants

In addition to the assignable values of the GridBagContraints
class, there are a large
number of constants whose chief
tasks include locating elements in the grid bag
layout. They
include directional constants like  NORTH, SOUTH, EAST,
WEST,
NORTHEAST,  NORTHWEST, SOUTHEAST, and
SOUTHWEST.  There is
also a CENTER constant. 

HORIZONTAL causes resizing horizontally but not vertically.
VERTICAL is opposite to HORIZONTAL. NONE is used to
specify
a component will not be resized. REMAINDER makes
it's component the last component in its column or row.
RELATIVE specifies a location that is either next to last or
next to previous.

The GridBagLayout class has a single no args constructor.
It defines two versions of addLayoutComponent( ) to add
a component to the grid bag and associate it with a
particular GridBagContraint object. In a grid bag the area
that is assigned to each component occupying a cell in
the grid is called the component's display area.

The GridBagConstraint object dictates how the component
will be shown in it's display area. How the components are
displayed will be influenced by the component's container.
GridBagConstraint objects are customized by setting one
or more of it's instance variables.

The constraint object for any component can be retrieved
using the GridLayout's getConstraints( ) method. The
setConstraints( ) method is used to set constraints on a
component before it is added to the layout.
 

Observation of the Effects of the GridBagConstraint Properties

GridBagLayout can at first be difficult to understand. It
uses a popular metaphor where a set of objects are defined
and then constraints are applied to them to control their
behavior. Looking at each constraint property in isolation
helps to unravel it's secrets. If the fill is set to 'both', the
components will fill the zones they occupy in both horizontal
and vertical directions. If no 'fill' is assigned and weight
values are set to zero the components will assume their
preferred size.

With even a small weight assignment the components
will fill their areas. The ipadx and ipady variables increase
the size of components incrementally in pixels from their
preferred sizes. Using the relative and remainder variables
specifies a relationship between two components in how
they divide a row. The gridwidth and gridheight can be used
to specify the number of rows or columns that a component
occupies.

Whatever changes are made before the setConstraints( )
method is called, are applied.  In code below, a text area
is set to a grid height of 6.


Example
  

constraints.gridheight=6;


Six buttons that are added next and have gridheights of
just 1. They are then set to take up the remainder of their
rows with the next line.


Example
 

constraints.gridwidth =GridBagConstraints.REMAINDER;

This way 6 buttons share the same vertical space as the
text area component at the bottom of the GUI.


Basic GridBag Strategy

The basic approach to using GridLayout is to first create
a GridLayout and set it to a container using the setLayout( )
method. Then a GridBagConstraint object is created. It's
variables are assigned values and the setConstraints( )
method is called to set theses constraints to the components.
The components are then added to the container. After
adding, the constraints object can be changed to effect
new changes on the next components that will be added
to the container.

// comments in red in the following code sample may make this clearer

 
GridBagLayout Code Sample

Following is a GridBag sample that shows many of the
constraints in action. This
is done in classic AWT. To
convert this class to Swing all the components would

go to their 'J' form counterparts. The javax.swing package
would need to be imported.
Then JFrame would need
require the use of getContentPane( ) for setting the

layout and adding components. 

 
GridBagLayout Example

import java.awt.*;
import java.util.*;

  public class GridBag extends Frame {
              GridBag(){
       GridBagLayout gridbag = new GridBagLayout();
       GridBagConstraints constraints = new GridBagConstraints();
       setFont(new Font("Helvetica", Font.PLAIN, 14));
       setLayout(gridbag);

        // above the gridbag and constraints object are created and layout set

    Button buttonVT1=new Button("Very Top 1");
    Button buttonVT2=new Button("Very Top 2");
    Button buttonVT3=new Button("Very Top 3");    // create components
    constraints.weightx = .2;                                      
    constraints.fill = GridBagConstraints.BOTH;       // apply values to properties
    gridbag.setConstraints(buttonVT1, constraints);
    gridbag.setConstraints(buttonVT2, constraints);  // map properties to components
    add(buttonVT1);
    add(buttonVT2);                                  // add effected components to the GUI

    constraints.gridwidth = GridBagConstraints.REMAINDER;  // do more property changes
    gridbag.setConstraints(buttonVT3, constraints);

    add(buttonVT3);

     Button buttonT2 = new Button("Top 4");
     constraints.weightx =2.0;
     constraints.weighty =1.0;
     constraints.gridwidth = GridBagConstraints.REMAINDER;
     gridbag.setConstraints(buttonT2, constraints);
     add(buttonT2);   

     Button button5 = new Button("Five");
     constraints.gridwidth = 1;

     constraints.weightx = 1.0;
     constraints.weighty = 1.0;
     gridbag.setConstraints(button5, constraints);
     add(button5);

     TextArea jta=new TextArea("Text");
     constraints.gridwidth = GridBagConstraints.REMAINDER;
     constraints.weightx =2.0;
     constraints.weighty =1.0;
     gridbag.setConstraints(jta, constraints);
     add(jta);  

     Button button6=new Button("Six");
     constraints.gridwidth = GridBagConstraints.REMAINDER;
     constraints.weightx =1.0;
     constraints.weighty =1.0;
     gridbag.setConstraints(button6, constraints);
     add(button6);   

     TextArea jta2=new TextArea("2nd Text Area");
     constraints.fill = GridBagConstraints.BOTH;
     constraints.gridwidth = 12;
     constraints.gridheight=6;
     constraints.weightx = 2.0;
     constraints.weighty = 1.0;
     gridbag.setConstraints(jta2, constraints);
     add(jta2);

     Button button7=new Button("Seven");
     Button button8=new Button("Eight");
     Button button9=new Button("Nine");
     Button button10=new Button("Ten");
     Button button11=new Button("Eleven");
     Button button12=new Button("Twelve");

     constraints.gridwidth =GridBagConstraints.REMAINDER;
     constraints.gridheight = 1;
     constraints.weightx = 1.0;
     constraints.weighty =1.0;
     gridbag.setConstraints(button7, constraints);
     gridbag.setConstraints(button8, constraints);
     gridbag.setConstraints(button9, constraints);
     gridbag.setConstraints(button10, constraints);
     gridbag.setConstraints(button11, constraints);
     gridbag.setConstraints(button12, constraints);
     add(button7);
     add(button8);
     add(button9);
     add(button10);
     add(button11);
     add(button12);
     this.setSize(700, 450);
     this.setVisible(true);
     }
     public static void main(String args[]){
     new GridBag();
   }
 }

Many authors and Java programmers have their own favorite
'recipes' for using GridBag layout which attests to it's great
power and flexibility.

It is important if you need to use the GridBag Layout to check
the JDK documentation on how each facet of the constraint
class works. 



New Swing Layouts



BoxLayout

The Swing API adds a number of new layouts. Most are
custom designed for specific components and are not
made for the general utility of the GUI programmer. One
that is accessible is the BoxLayout. The BoxLayout

interface can be implemented or the Box component used
which provides a default
implementation of the BoxLayout.

BoxLayout allows multiple components to be layered out
either vertically or horizontally.
The components will not
wrap so, for example, a vertical arrangement of components
will
stay vertically arranged when the frame is resized.

Nesting multiple panels with different combinations of
horizontal and vertical can create an effect similar to
GridBagLayout. You
can nest multiple boxes and add
components to them to get the arrangement you want.

// nesting BoxLayouts yields flexible layouts similar to GridBagLayout

When you create a BoxLayout, you specify whether its
major axis is the X axis, ( horizontal
) or Y axis, ( vertical ).
Components are
arranged from left to right (or top to bottom),
in the same order as they were added to
the container.


The Box Class

Instead of using BoxLayout directly, many programs use
the Box class. The Box class
provides a lightweight
container that uses a BoxLayout. Box also provides
handy
methods to help you use BoxLayout well.

BoxLayout attempts to arrange components at their
preferred widths (for left to right
layout) or heights (for
top to bottom layout). For a left to right layout, if not
all the
components are the same height, BoxLayout
attempts to make all the components
as high as the
highest component. If that's not possible for a particular
component,
then BoxLayout aligns that component
vertically, according to the component's Y
alignment.

// Y layouts are uniform in width, X layouts are uniform in height

By default, a component has an Y alignment of 0.5, which
means that the
vertical center of the component should
have the same Y coordinate as the vertical
centers of
other components with 0.5 Y alignment.
// from the JDK API

Similarly, for a vertical layout, BoxLayout attempts to
make all components in the
column as wide as the widest
component; if that fails, it aligns them horizontally
according
to their X alignments.

Struts & Glue

A strut can be used to place a fixed amount of space
between two components. Struts can be set with the
createHorizontalStrut( ) or createVerticalStrut( ) methods.
A rigid area is an an invisible component that always
takes up the same amount of space and is created using
the createRigidArea( ) method. Glue is a flexible area
that is created with the createGlue( ) method.

The create methods for glue and struts create flexible and
rigid areas that, when resized,
will re-size proportionately
or remain fixed in size respectively.

Resize the following and you will see the rigid areas
between the two middle labels remains unchanged
while the glue parts re-size with the container.

Box Code Example

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

class Glue extends JFrame{
      Glue() {
        
      Box bx1=new Box(BoxLayout.Y_AXIS);
     
      JLabel j1=new JLabel("A Little Glue ");
      j1.setFont(new Font("Helvitica",Font.BOLD, 16));
      j1.setOpaque(true);
      j1.setBackground(Color.green);
      bx1.add(j1);
     
      Component glue1 = Box.createGlue();
      bx1.add(glue1);
      // glue    

      JLabel j2=new JLabel("A Rigid Area");
      j2.setFont(new Font("Helvitica",Font.BOLD, 16));
      j2.setOpaque(true);
      j2.setBackground(Color.yellow);
      bx1.add(j2);
     
      Component rigid =Box.createRigidArea(new Dimension(450,100));
      bx1.add(rigid);
      // rigid area
  
      JLabel j3=new JLabel("Vertical Strut");
      j3.setFont(new Font("Helvitica",Font.BOLD, 16));
      bx1.add(j3);
      j3.setOpaque(true);
      j3.setBackground(Color.red);
     
      Component strut =Box.createVerticalStrut(100);
      bx1.add(strut);
     
      JLabel j4=new JLabel("More Glue! ");
      j4.setFont(new Font("Helvitica",Font.BOLD, 16));
      j4.setOpaque(true);
      j4.setBackground(Color.white);
     
      bx1.add(j4);
     
      Component glue2 = Box.createGlue();
      bx1.add(glue2);
     
        getContentPane().add(bx1);
  
      setDefaultCloseOperation(DISPOSE_ON_CLOSE);
      setSize(500,400);
      setVisible(true);
      }
      public static void main(String[]args){
      new Glue();
      }
     }



Self Test                          Self Test with Answers



1)  Which of the following is able to display RTF files

a) JPasswordField
b) JTextField
c) JTextArea
d) JEditorPane

2) What is the name, in Java, of the component that is used to represent sub-sections
      of a document?

a) Blocks
b) Paragraphs
c) Elements
d) Lines


3) Which of the following layout managers is effectively replaced by JTabbedPane

a) BoxLayout
b) FlowLayout
c) GridLayout
d) CardLayout



4) True or False. Absolute x-y coordinate based layouts are possible using the
      NullLayout manager.

5) Which of the following statements regarding BorderLayout is least correct?

a) Any region that is left out will be filled by the CENTER region if the CENTER
    region is added.
b) Using the getContentPane( ).add( ) with a component and not specifying a region
    will by default add to the center.
c) If a second components is added to a region where another component is already
    resident, the second component added is ignored.
d) BorderLayout has the constants, NORTH, SOUTH and CENTER.


6) Which of the following layouts is a swing layout rather than an awt layout?

a) GridBagLayout
b) CardLayout
c) BoxLayout
d) CardLayout


7) Which of the following statements is not correct?

a) GridLayout will adjust the number of columns depending on the number of
    components added to the grid.
b) GridLayout allows components to retain their preferred size and shape.
c) GridLayout is used to create rows and columns in uniform grid
d) GridLayout is one of the AWT layout managers.


8) Regarding BoxLayout which statement is not correct?
a) Box Layout allows the creation of a set of components along a horizontal
    or vertical access.
b) BoxLayout allows the creation of rigid areas.
c) BoxLayout allows the creation of flexible area.
d) BoxLayout allows the creation of rows and columns.


Exercise



Create in 5 JPanel classes an example of each of the following.

a) A null layout
b) A flow layout
c) A grid layout
d) A border layout
e) A box layout

Each panel should have their layouts set using setLayout( ) and
populated with a mixture of JLabels, and JTextComponents that
clearly show the mapping strategy that each layout supplies.

You can use a 'LayoutRunner' class that extends JFrame to hold and
display these panels.  You could add the instantiations and add methods
to load them all into the runner class. Use commenting to cause anyone
of them to show to screen.

You can also make nest them all in a single grid layout so they all
are visible at once. You might use a container set to a border layout.
Inside it's center region create a panel set to a 4 x 4 grid which then
will nest the other four variations.

Finally you can used JTabbedPane to hold each of the variations.
Anyone one approach will do.

// Later when we cover event processing we might add buttons that
// allow selection of the various panels within the same GUI window.


If possible supply screen shots of your layouts with your submissions.


Optional

Add a gridbag layout to the list above