Applets II & Complex JComponents
Peter Komisar  ©     Conestoga College version 1.0

  Applets II


This note is a continuation of the first note on applets.

Converting a Stand Alone Application to an Applet  

To convert a standalone application to an applet, the layout
manager must be
set to match in the two frames. The work
that is done in the constructor can
be transferred to init( )
method. Any necessary functionality of main( ) may
be
transferred to start( ), stop( ) or paint( ). The main( ) method
can be left in
the applet as main( ) is not called.


The getDocumentBase( ) &
getCodeBase( ) Methods



Applet also defines two useful methods that can reference
the location of the Java applet code and the location of the
HTML code that contains the tag for the Java applet. They
are handy because you may not know exactly what these
paths are. The getDocumentBase( ) method returns the
URL of the directory containing the HTML document (which
is referencing an applet). The getCodeBase( ) method returns
the URL representing the directory where the applet class
file resides.
 

Applet's getCodeBase and getDocumentBase( )  methods

 URL  getCodeBase( )      
// returns the code base for the applet class file as a URL
 URL getDocumentBase( )
// returns the URL naming the directory of the document
// containing the applet the applet is embedded.

Example       

Image cat = getImage( getDocumentBase( ), "Cat.jpg" );
 

getCodeBase & getDocumentBase( ) Code Sample

//<applet code="WhatDir.class" width=400 height=200></applet>

import java.net.*;
import java.awt.*;
import java.applet.*;
 

public class WhatDir extends Applet{
   String s1,s2,s3,s4;
   URL code,doc;
 public void init(){
   code=getCodeBase();
   doc=getDocumentBase();
   s1="Code Base";
   s2=code.toString();
   s3="Document Base";
   s4=doc.toString();
   }
public void paint(Graphics g){
  g.drawString(s1,40,20);
  g.drawString("_______________________",40,22);
  g.drawString(s2,40,40);

  g.drawString(s3,40,80);
  g.drawString("_______________________",40,82);
  g.drawString(s4,40,100);
  }
}

It is interesting to note when you run this code using
source code with the APPLET tag commented out, that
the getDocumentBase( ) method points to the source
code file, recognizing it to be the 'HTML' document
associated with the applet.



AppletContext



AppletContext is an interface that is implemented by an
object that represents the
Java runtime environment that
the applet runs in. To use any of AppletContext's many
useful methods
, one needs to get a handle to the
AppletContext. The following example shows the method
that is used to acquire a reference to the AppletContext
object

Example   

AppletContext context= getAppletContext( );


AppletContext defines some interesting methods such
as the getApplet( ) method
which returns the name of
the applet in the document and getApplets( ) which

returns all the applets in the document. 

// getApplet( ), getApplets( )

AppletContext also defines the method showDocument( ),
either taking a URL or a URL as a path to a file named as

a String. The method launches an HTML page in the
browser which is showing
the applet. This could be handy
to use with HTML frames where the applet
would reside
in one frame and launched HTML pages would show in
an adjacent
frame.

// showDocument( )

The showStatus( ) method will show in the status bar
at the button of
the browser. The code below shows
the showDocument( ) and showStatus( )
methods being
used. The showStatus( ) method is easy to demonstrate
in
appletviewer however, with modern browsers, the
status message is changing
all the times with browser
events the showStatus( ) method may only show
a
message for an instance.
// showStatus( )
 

AppletContext Code Sample

import java.net.*;

 // <applet code="ShowD.class" width=400 height=100></applet>

 public class ShowD extends Applet{
    public void init(){
    try{
    URL url=new URL("http://sentex.net/~pkomisar/FloweredReptile");
    getAppletContext( ).showDocument(url);
    }catch(MalformedURLException me){}

    }

    public void paint( Graphics g){
      g.setFont(new Font("Monospaced", Font.BOLD, 22));
      g.drawString("OK, It's Hello World", 50, 60 );
      getAppletContext( ).showStatus( "Puts the message in the browser status line" );

    }
 }


Getting Parameters from the HTML Document



Just as values passed into main( ) in a standalone program
come in as String values, values passed into an applet
from an HTML document also come in as String objects.
Steps have to be
taken to convert the values to other
forms.

The following applet example reads three parameters
from the HTML page and stores their values in instance
variables. Three parameters are specified in the Applet
tag. All the values are strings. Note quotes allow multiple
words with spaces An applet reading these values uses
the NAME identifiers as parameters to the getParameter( )
method.

// values are read with the getParameter( ) method

Going in, the case used to describe the value stored by
the 'name' attribute is not significant. The string value
returned by the method is in Java's case-sensitve world
and thus is case-sensitve.

// Going in, on the HTML side, is not case-sensitive
// while the Java return values are case sensitive


The following example shows this where the string in
'name' is 'artisto'. The getParameter( ) method is able
to reference that name value in a case insensitive
fashion. The value stored in the 'value' reference though,
now that it is inside the Java program will be case
sensitive.

Example     

// in the applet tag
<param name="artisto" value="Pablo Picasso">

// in the applet

String value = getParameter("ArTiStO");

// parameter pasted into getParameter( ) is not
// case sensitve
while the String value returned is  

The following code sample shows a few techniques to
avoid creating a null pointer exception from being thrown.
Member variables of the class are explicitly set to default
values to insure they are not null. In addition, 'try catch'
blocks are used to catch for Exception class which will
capture potential occurrences of exceptions such as
ArithmeticFormatException or NullPointerException.
Finally logic tests are done to confirm that values are not
equal to null. These safety features help insure the applet
doesn't fail in a client's browser.
 

Parameter retrieving code sample

import java.awt.*;
import java.applet.*;
import java.applet.Applet;
import java.net.*;

/*
<applet code="Params.class" width =300 height=300>
    <param name="artisto" value="Pablo Picasso">
    <param name=title value="Bather With Beach Ball">
    <param name=image value="Bather.jpg">
    <param name=imageNo value="32">
    </applet>
*/
public class Params extends Applet {
      String testedValue;
      Image ii;
      URL ui;
      TextField report;
      String _artist = "artist name";
      String _title  = "name of painting";
      String _image = "image";
      String _imageNumber="0";
      int number=0;

    public void init( ) {
           setBackground(Color.darkGray);
           String s=null;
           setLayout(new BorderLayout());
           report=new TextField("Report");
           report.setBackground(Color.gray);
           report.setForeground(Color.white);
            add(report,BorderLayout.SOUTH);
            testedValue = getParameter("ArTiStO");
       // shows that going in the values stored in NAME is not case-sensitive
          if (testedValue != null){
            _artist = testedValue;
            }
          testedValue = getParameter("title");
          if (testedValue != null){
            _title = testedValue;
            }
          testedValue = getParameter("image");
          if (testedValue != null){
          _image = testedValue;
          }
           ii =getImage(getCodeBase(),_image);
          testedValue = getParameter("imageNo");
          if (testedValue != null){
          _imageNumber=testedValue;
          }

       try{
          number = Integer.parseInt(_imageNumber);
          s="# "+ number +" " + _title  + " " + _artist;
          report.setText(s);

           }
          catch(Exception e){
          e.printStackTrace();
          }
     }             // end of init( )

public void paint(Graphics g){
   if(ii!=null)     // another null pointer avoidance
   g.drawImage(ii,58,30, this);
   }
}


// The following Plug-in Information, as well as the following
material regarding additional JComponents is not on the exam.


The Java Plug-In


Early on, power politics were at play with Java support
in browsers.
Disagreements between Sun and Microsoft,
as well as Netscape's sometimes tardy adoption
of newer
versions of Java for their browser led Sun to adopt a
strategy of
providing newer JDK runtime environments
in the form of 'plug-ins'. This enabled
support for Swing
and more sophisticated applets built on
JApplet. 

Netscape 4.77 and Internet Explorer 5.x shipped with
support  for old version
s of the JDK circa 1.7.x. They
can run applets built using AWT. For
older browsers to
support Swing the JDK plug-in has to be downloaded. 

Around IE 5.x, Microsoft announced it was dropping
support for Netscape style
plug-ins. (Plug-ins were
popularized by Netscape.) IE 5.5 was shipped without
support
plug-ins. As well Explorer was shipped without
Java support.

// this was the bad old days. Sun and Microsoft have
// since 'buried the hatchet' more or less!

Ever astute, Sun has the Active-X style plug-in for Java
ready to go for Explorer. The plug-in approach is really a
better way to go as the user is not restrained by
implementation timetables of the browser providers.

Later, AOL's Netscape 6.2 did ship with support for Swing
built in. On the other hand, the new open-source Mozilla
(as well as the browser spin off, 'Firefox')  aimed to lighten
downloading
and left it to the user to download the Java
plug-in.

~2007

As 2006 ends, Netscape is in version 7, IE has just entered
version 7 and Firefox 2 has been released. A majority of
connections are highspeed and downloaded Java support
as a plug-in is fast and trouble free.


Solutions Allowing Redirects to Obtain the Java Plug-In

The following paper at the Sun site offers solutions
to control what has been happening with Applets in
conjunction with the HTML world. 

'Using OBJECT, EMBED & APPLET tags in Java Plug-In' 
can be  found at the following URL,

http://java.sun.com/j2se/1.5.0/docs/guide/plugin/developer_guide/using_tags.html

We have seen in this note that the Object tag is the
recommended replacement for the Applet tag.  A
limitation of the Applet tag is that it does not allow a
redirect to take place that would allow the browser to
interrupt rendering the page and 'run off' to procure
the Java Plug-In. 

Using Windows Explorer

Window's Explorer is said to be compliant with the
W3C's HTML recommendation to use the OBJECT tag.
(Though we found the 'off the rack' form of the OBJECT
tag didn't seem to work in IE, there are other formulations
involving adding other attributes with unique identifiers
that would have have allowed to Object tag to work.)

The Object tag allows deferring an Applet's execution
until after the Plug-In is obtained. The way this mechanism
works is that the OBJECT Tag's 'classid' and 'codebase'
attributes are used to  redirect to the Sun site to do the
Plug-In download and PARAM tags are substituted to
supply the class information needed to run the specific
Java applet.


Example of an Original Applet Tag  


 // from Using OBJECT, EMBED and APPLET tags in Java Plug-In, at the Sun site.

<APPLET code="XYZApp.class" codebase="html/" align="baseline"
    width="200" height="200">
<PARAM name="model" value="models/HyaluronicAcid.xyz">
    No Java 2 SDK, Standard Edition v 1.4.2 support for APPLET!!
</APPLET>


New Object Tag that Allows Redirect to Get Plug In

<OBJECT classid="clsid:CAFEEFAC-0014-0002-0000-ABCDEFFEDCBA"
    width="200" height="200" align="baseline"
    codebase="http://java.sun.com/products/plugin/autodl/jinstall-1_4_2-windows-i586.cab#Version=1,4,2,0">
    <PARAM name="code" value="XYZApp.class">
    <PARAM name="codebase" value="html/">
    <PARAM name="type" value="application/x-java-applet;jpi-version=1.4.2">
    <PARAM name="model" value="models/HyaluronicAcid.xyz">
    <PARAM name="scriptable" value="true">
        No Java 2 SDK, Standard Edition v 1.4.2 support for APPLET!!
</OBJECT>


Using Netscape Navigator

Netscape on the other hand, uses the EMBED tag to obtain
plug-ins. The EMBED tag is a sophisticated version of the
Applet tag that still retains many of the same attributes. This
allows the EMBED tag to redirect to obtain the plug-in while
still retaining some of the 'looks' of the old APPLET tag.


EMBED Tag Version of the Original Applet  
    // from Sun site paper  

<EMBED type="application/x-java-applet;jpi-version=1.4.1" width="200"
   height="200" align="baseline" code="XYZApp.class"
   codebase="html/" model="models/HyaluronicAcid.xyz"
   pluginspage="http://java.sun.com/j2se/1.4.1/download.html">
<NOEMBED>
   No Java 2 SDK, Standard Edition v 1.4.1 support for APPLET!!
</NOEMBED>
</EMBED>


Giant Fudge Combo That Works in Both Browsers

A 'Fudge' exists that will please 'geeks' everywhere. It is
based on the fact that IE has a proprietary tag, COMMENT
that it recognizes but Netscape ignores. Also, Netscape
is said to not recognize the OBJECT tag so a solution exists
where the EMBED tag is nested inside IE COMMENT tags
inside the OBJECT tag. This results in a tag that will prompt
for the latest series of Java Plug-In in both Browser
environments.

// To make this work the value specified to 'classid' and 'codebase'
// may need to be updated.



'Fudge' That Works in Both IE and Netscape
   // from Sun site paper


<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
    width="200" height="200" align="baseline"
    codebase="http://java.sun.com/products/plugin/1.4/jinstall-14-win32.cab#Version=1,4,0,mn">
    <PARAM NAME="code" VALUE="XYZApp.class">
    <PARAM NAME="codebase" VALUE="html/">
    <PARAM NAME="type" VALUE="application/x-java-applet;jpi-version=1.4">
    <PARAM NAME="model" VALUE="models/HyaluronicAcid.xyz">
    <PARAM NAME="scriptable" VALUE="true">
    <COMMENT>
        <EMBED type="application/x-java-applet;jpi-version=1.4" width="200"
           height="200" align="baseline" code="XYZApp.class"
           codebase="html/" model="models/HyaluronicAcid.xyz"
           pluginspage="http://java.sun.com/j2se/1.4/download.html">
            <NOEMBED>
                No Java 2 SDK, Standard Edition v 1.4 support for APPLET!!
            </NOEMBED>
        </EMBED>
    </COMMENT>
</OBJECT>


We switch gears in the next section to mention some main
Swing components that were not covered in the Swing
section.



JTabbedPane, JSplitPane & ToolBar


JTabbedPane

JTabbedPane is a component that allows several panels
to be displayed one at a
time. Tabs are provided to allow
selection of the pane the user wishes to see. This
class
supplies behaviour similar to what was produced when
the AWT CardLayout
manager was used.

JTabbedPane defers complexity to it's add methods and
keeps
it's constructors simple. It has only two constructors,
one a no-arg constructor and
one allows specifying where
the tabs are placed, top, bottom, left or right. The
default
location is top. These can be specified using the
SwingConstants class.

The addTab methods are overloaded to take a String to
label the tab and a
component to display, or a String, an
Icon and a Component, or a String, Icon,
Component
and a tool tip.

 

JTabbedPane Code Sample  // once again you need to supply your images

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

class Tabber extends JFrame{
      Tabber(){
      ImageIcon ike1=new ImageIcon("Apples.jpg");
      ImageIcon ike2=new ImageIcon("Cezanne.jpg");
      JLabel pic1=new JLabel(ike1);
      JLabel pic2=new JLabel(ike2);
      JLabel cover=new JLabel("     Early 20th Century ");

      JTabbedPane tabpane=new JTabbedPane( SwingConstants.TOP );
       tabpane.addTab("Folio",cover);
       tabpane.addTab("Picasso", pic1);
       tabpane.addTab("Cezanne", pic2);
       getContentPane().add(tabpane);
       setSize(400,400);
       setVisible(true);
     }
     public static void main(String[]args){
     new Tabber();
     }
 }


JSplitPane

JSplitPane manages two child components that can be
splitted vertically or horizontally, using the class constants
JSplitPane.HORIZONTAL_SPLIT or  VERTICAL_SPLIT.
The dividing bar can be dragged to change the relative
proportion of the viewable area each of the 'twins' occupy.
The dividers location can be set with the setDividerLocation( )
method.

This method is overloaded to take either an int value
representing pixels. The overloaded version of the method
takes a double value between 0.0 and 1.0 representing
the relative proportion that the two child components
occupy. The documentation states this second version
works based on an earlier provided preset value. The
implication is that the second method may be used
dynamically change to change the divide point.

In the code below, one way of getting the second version
of the function to work is shown.

The orientation of the frames can be set when the
component is constructed or after using a setOrientation( ) 
method. The minimum size of a frame can be specified
with the setMinimumSize( )  method. There are a number
of other methods available to control the details of this
component which are outlined in the JDK documentation.
They are all straight forward to use.


JSplitPane Code Sample

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

// comment the setDividerLocation method
// called in main( ) after running it with the
// first setDividerLocation method.

      class ChatGUI extends JFrame{
             JTextArea chat1,chat2;
          JSplitPane talk;
             ChatGUI(String s ){
                        super(s);
                       JPanel subIn=new JPanel( );
                             subIn.setLayout(new BorderLayout( ));
                             JLabel in=new JLabel("INCOMING");
                             subIn.add(in,BorderLayout.NORTH);
                             chat1 = new JTextArea( );
                             JScrollPane top = new JScrollPane(chat1);
                             subIn.add(top,BorderLayout.CENTER);
 

                       JPanel subOut=new JPanel( );
                             subOut.setLayout(new BorderLayout( ));
                             JLabel out=new JLabel("OUTGOING");
                             subOut.add(out,BorderLayout.NORTH);
                             chat2 = new JTextArea( );
                             JScrollPane bottom = new JScrollPane(chat2);
                             subOut.add(bottom, BorderLayout.CENTER);

                             talk = new JSplitPane
                              (JSplitPane.VERTICAL_SPLIT,subIn,subOut);
                              talk.setDividerLocation(250);
                  repaint();
                 
                  talk.setOneTouchExpandable(true);
                             JPanel envelope=new JPanel( );
                              envelope.setLayout(new BorderLayout( ));
                              envelope.add(talk);

                             getContentPane( ).add(envelope);
                             setSize(500, 400);
                             setVisible(true);
                 }            
                            

               public static void main(String[]args){
                            ChatGUI chat = new ChatGUI("A GUI For a Chat Program");
             //   chat.talk.setDividerLocation(.33);
                }
               }


JToolBar

JToolbar is a floatable 'Menu Bar' container. It can be
populated with icons that symbolized different tools. It
can occupy space vertically or horizontally. Although
the component is floatable, this may lead to unpredictable
placement after resizing so it has been recommended in
some sources to set the floatability property to false
using the setFloatable( ) method.

Toolbar Code Sample

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

class Tool extends JFrame{
public static void main(String[]args){
  Tool tool=new Tool();
  JToolBar toolbar = new JToolBar();
  toolbar.setFloatable(false);
  toolbar.add(new JButton("button 1"));
  toolbar.add(new JButton("button 2"));
  toolbar.add(new JButton("button 3"));
  tool.getContentPane().add(toolbar, BorderLayout.SOUTH);
  tool.setSize(300,300);
  tool.setVisible(true);
  }
}




JList & DefaultListModel


Complex components are made up of several classes.
JList is simpler than JTable, and in fact is a sort of
one-dimensional version of JTable. By looking at this
component in some depth you will be better prepared
to add JTable to your 'toolkit'.

JList & DefaultListModel

JList represents an ordered list of elements. JList supplies
a user with a selection of one or more items. It can be
used traditionally using a non-model approach or more
efficiently using the underlying MVC architecture. The
constructors supply a simple approach to providing a
short list using an array or vector.

When this approach is taken a read-only version of the
model is constructed.
This limits how you can manipulate
the model that represents your data. The
following line
shows that you can read your data but can't use a set
method
to alter it. The getSize( ) and getElement( )
methods can be used to query the model.

Example         

  String[] offices = {"Cairo", "Venice", "Berlin", "Budapest"};
  JList company = new JList(offices);
  ListModel model = company.getModel( );
  int size = model.getSize( );
  for(int i=0;i<model.getSize( );i++)
      System.out.println(model.getElementAt(i));

 

DefaultListModel

AbstractListModel is a implementation of the ListModel
interface. DefaultListModel
class is a subclass of the
AbstractListModel class and based on a Vector as the
storage class. It
generates ListData events. If you look
at DefaultListModel's methods they include
the set of
methods you could call on a vector.

The default list model provides methods to manipulate
the data while the JList itself has methods that control
the view of the data. I
n the following example the model
is not just read only and a new value, London,
was added
using a set method.

Example

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

 public class ListFrame extends JFrame {
     ListFrame(String s ){
      super(s);
      String[] offices = {"Cairo", "Venice", "Berlin", "Budapest"};
      DefaultListModel dmod=new DefaultListModel( );
      for(int i=0;i<offices.length;i++){
           dmod.addElement(offices[i]);
       System.out.println(offices[i]);
       }
            // add an element to DefaultListModel
        dmod.addElement("London");
            System.out.println();
            JList company = new JList(dmod);
            ListModel model = company.getModel( );
            int size = model.getSize( );
            
      for(int i=0;i<model.getSize( );i++)
               System.out.println(model.getElementAt(i));
           getContentPane().add(company);
           setSize(400,250);
           setVisible(true);
          setDefaultCloseOperation(EXIT_ON_CLOSE);
          }
     public static void main (String args[]) {
          new ListFrame("A class extending JFrame" );
          }
      } 

This is still not the most efficient technique as a copy of
the data was used to load and
create another copy into
memory. An abstract list model extension can be built
around
a collection of data allowing the list to be modeled
on a single data source.


AbstractListModel & the ListModel Interface


When data
comes from a big array or vector, you may
take the next
step and implement the ListModel interface.
ListModel defines the getSize( ) method
we saw earlier
and the getElementAt( ) method. These two methods
provide the basic
functions of supplying the size of the
list and providing access to any element in it.
The interface
also defines the listener methods for events representing
changes to the
list.
 
The AbstractListModel is an abstract class that is provided
to take care of some of
the event handling details for you.
It leaves only the getSize( )  and getElementAt( ) methods

for the user to implement.

Following the AbstractListModel is implemented. The Swing
package defines a a new ActionListener for JList called
ListSelectionListener. The AWT
List class used the
ItemListener of the AWT event package. There is also a
listener that
responds to items being added and removed
to the list that we might have implemented.
This is the
ListDataListener interface.

A major advantage of the following code is that only one
data model is used and as such is more efficient in terms
of both performance and memory usage.

 

Code Sample

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

 class BranchModel extends AbstractListModel{
       String[] offices = {"Cairo", "Venice", "Berlin", "Budapest", "Paris"};

       public int getSize( ){
          return offices.length;
          }
       public Object getElementAt(int index){
          return(offices[index]);
          }
      }

class Destination extends JFrame  implements ListSelectionListener{
       JTextField destination;
       JList company;
       ListModel model;

      Destination(){
           model=new BranchModel( );
           company = new JList(model);
           company.addListSelectionListener(this);
           getContentPane( ).add(company);
           destination =new JTextField( );
           getContentPane( ).add(destination,BorderLayout.SOUTH);
           pack();
           setVisible(true);
           }

public void valueChanged(ListSelectionEvent e){
 destination.setText( (String)company.getSelectedValue() );
  }
public static void main(String[]args){
  new Destination();
  }
 }


JTable

JTable is a highly complex visual component made up
of several cooperating parts. The table is designed to
provide an efficientview of data stored in a data model.
Much of JTables functionality is delegated to support
classes. JTable and related classes are made available
by importing the table package.

Example    

import javax.swing.table.*;

Table Support Classses

A JTable header is represented by  JTableHeader class
object. Columns are instances of TableColumn class.
Selection is controlled by ListSelectionModel objects.
Table data is represented by TableModel class objects.
TableCellEditor class objects are responsible for the
appearance of table cells. Finally the TableCellRenderer
class is used to paint unedited cells.


Components of JTable


JTable Constructors

JTable has many constructors including a no-arg constructor,
and a constructor that takes the number of rows and columns.
These objects use the DefaultTableModel to represent data.
Another constructor is more elaborate and allows passing in
an Object array of arrays and an array storing column names.
A fourth constructor is built on a TableModel. A fifth allows
passing in TableModel and TableColumnModel, a sixth accepts
TableModel, TableColumnModel and ListSelectionModel. Finally
there is a constructor that takes a vector storing row data and
a vector holding column names. The constructors are listed
briefly in the following table.

Brief Summary of JTable Constructors
 
 JTable( )   - a  JTable initialized with default data, column 
   and selection models.
 JTable(int numRows,
         int numColumns) 
 - a JTable with numRows and numColumns of 
    empty cells using DefaultTableModel.
 JTable(Object[][] rowData,
   Object[] columnNames) 
  - a JTable displaying two dimensional array values, 
     rowData, with  column names, columnNames.
 JTable(TableModel dm)    - a JTable initialized with a data model provided
    and a default column and selection model.
 JTable(TableModel dm,
 TableColumnModel cm) 
  - a JTable initialized data and column models 
     provided and a default selection model.
 JTable(TableModel dm, 
 TableColumnModel cm, 
 ListSelectionModel sm) 
 - a JTable initialized with a data, column and 
   selection models provided.


JTable is also able to take a vector representing row data
and a second vector representing columns.

The following example shows a simple approach to using
JTable. You will notice the getTableHeader method was
used to get a reference to the table header. This object
was then added to the north region of the frames border
layout. If this was not done explicitly, the column headings
would not have shown. The header has an interesting
property. The columns can be dragged and dropped allowing
them to be reordered using the mouse.

The table package which is nested inside the javax.swing
package has to be imported to get access to the JTableHeader
class. When a JTable is added to a scrollpane the viewport's
preferred size can be controlled using the ( excessively long)
setPreferredScrollableViewportSize( ) method. Intercell
spacing can be changed using the setIntercellSpacing( )
method.

The Table Grid Appearance

The color of the grid can be obtained using getGridColor
and grid color can be set with the setGridColor( ) method.
The table grid can be made visible or hidden using the
setShowGrid( ) method which takes a boolean true or
false value.  The methods setShowHorizontalLines( ) and
setShowVerticalLines( ) each take a boolean value and
can be selectively used to show either vertical or horizontal
table grid lines. These methods can be used in various
combinations to toggle the flags controlling the visibility of
the grid lines. The different aspects of JTable discussed so
far are contained in the first JTable example.
 

JTable Code Sample 1

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

class Table1 {
        Table1( ){
        JFrame frame=new JFrame(" JTable Example 1" );
        Vector rows = new Vector(3);
        Vector row1=new Vector(3);
        Vector row2=new Vector(3);
        Vector row3=new Vector(3);

         row1.addElement("Bill Dexter");
         row1.addElement("927-3393");
         row1.addElement("bill@bronze.ca");
         rows.addElement(row1);

         row2.addElement("Betty Barber");
         row2.addElement("828-1221");
         row2.addElement("bbarber@silver.uk");
         rows.addElement(row2);

         row3.addElement("Chris Copper");
         row3.addElement("424-5343");
         row3.addElement("ccopper@gold.net");
         rows.addElement(row3);

         Vector columns= new Vector(3);
         columns.addElement("Names");
         columns.addElement("PhoneNo");
         columns.addElement("E_mail");

         JTable table=new JTable(rows,columns);
         table.setGridColor(Color.pink);
         table.setShowGrid(false);
         table.setShowVerticalLines(false);
         table.setShowHorizontalLines(true);

         JTableHeader header=table.getTableHeader( );

         frame.getContentPane( ).add(table, BorderLayout.CENTER);
         frame.getContentPane( ).add(header, BorderLayout.NORTH);
         frame.setSize(400,300);
         //  frame.pack( );
         // pack( ) creates a frame just big enough to fit what's put in it.
         frame.setVisible(true);
         }
public static void main(String[]args){
         new Table1( );
         }
  }


JTable Selection Models

JTable supports several selection modes. An version
of ListSelectionModel
is used to control column and
row selection. The default implementation supplied is

DefaultListSelectionModel. Thus the selection modes
available for the rows of JList
are available for the
rows and columns of JTable. These include single and
multiple
selection modes where the multiple selection
modes may be sequential or random.

// supports ListSelectionModel

What is selected can be controlled using the methods,
setRowSelectionAllowed( ) &
setColumnSelectionAllowed( )
methods which are set to booleans, true or false. The
method
setSelectionMode( ) sets the selection mode
for both rows and columns. If a different
selection pattern
is needed for rows and columns, the getColumnModel( )
method
will return the column model and it's selection mode
can be set separately from the
row selection mode.

ListSelectionModel selection mode constants are listed
in the
following table.
 

ListSelectionModel Selection Mode Constants
 
 MULTIPLE_INTERVAL_SELECTION   - selects one or  more sequential indice ranges 
 SINGLE_INTERVAL_SELECTION   - select one contiguous range of indices at a time.
 SINGLE_SELECTION   - selects one list index at a time.


The cell background and foreground colors can be set with
the setSelectionBackground( ) and setSelectionForeground( )
methods. The following lines can be added to the previous
example.

Example 

table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
table.setSelectionBackground(new Color(255,250,240));
table.setSelectionForeground(Color.blue);


Selection Methods of JTable

Of JTable's many methods, some are designed to effect
the selection process.

setRowSelectionInterval( ) - Specifying two integers to the
setRowSelectionInterval( )
method defines a range (which
includes the rows specified by the two ints) that limit
the
number of rows that can be selected.

addRowSelectionInterval( ) - The addRowSelectionInterval( )
can be used to
increase the range selectable. There is a
similar pair of methods for column selection.

clearSelection( ) - This method clears the collection set.

getSelectedRowCount( ) - returns the number of rows that
are selected.


The TableModel Interface
// getRow/ColumnCount( ) & get/setValueAt( )


JTable uses a TableModel to represent data. The table
model defines the key
methods used to access and set
data to the model as well as to get the number
of rows
and columns. The model defines the getRowCount( )
and getColumn( )
count methods and the getValueAt( )
and setValueAt( ) methods. The model
also defines the
addTableModelListener( ) and removeTableModelListener( )

to register TableModelListeners for TableModelEvent
objects.

The TableModel Event Class

The TableModelEvent class defines among other constants
the INSERT
UPDATE and DELETE constants. This allow
determining if the table change
represents one of these types
of events. The TableModelEvent class has five
constructors
and the methods, getFirstRow( ), getLastRow( ), getColumn( )

and getType( ).

// model accomodates SQL


The TableColumnModel Interface

JTable columns have their own TableColumnModel which
defines the addColumn( ),
removeColumn( ), moveColumn( )
and setColumnMargin( ) methods for modifying
the model.
For querying the model there is the getColumnCount( ),
getColumnIndex( ),
getColumn( ), setColumnSelectionAllowed( ),
getColumnSelectionAllowed( ),
getSelectedColumns( ),
getSelectedColumnCount( ),setSelectionModel( ) and

getSelectionModel( ).

For registering listeners the interface includes the
addColumnModelListener( ) and removeColumnModelListener( )
methods.

The TableColumnModelEvent class

The TableColumnModel generates it's own event object
type which has a single
constructor and the getFromIndex( )
and the getToIndex( ) methods. This event
object is
generated when the column is added or removed or moved.


AbstractTableModel & DefaultTableModel
 
AbstractTableModel

The AbstractTableModel class is an abstract implementation
of the TableModel
interface. Though the class is abstract
supplies concrete definitions for most of
the methods of
TableModel. One approach to building a JTable is to extend
the
AbstractTableModel and supply the JTable constructor
an object of the model
subclass. In extending AbstractTableModel
only the following three methods
need to be provided.

AbstractTableModel Methods that must be overidden.

  public int getRowCount( );
  public int getColumnCount( );
  public Object getValueAt(int row, int column);

This abstract class provides default implementations for most
of the methods in the
TableModel interface. It takes care of
the management of listeners and provides
some conveniences
for generating TableModelEvents and dispatching them to the

listeners.

If the table is going to have column headers, the methods
related to column
names must also be overidden.


AbstractTableModel Code Sample

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

class AbTab2 extends JFrame implements ListSelectionListener{
            ListSelectionModel selectModel;
         AbTab2( ){
            CourseModel model = new CourseModel();
            JTable table=new JTable(model);

            /* get selection model using getSelectionModel( ) register
                 'this' as the listener with the listselection model */

            selectModel=table. getSelectionModel( );
            selectModel.addListSelectionListener(this);

            JTableHeader header= table.getTableHeader( );
            getContentPane().add(header,BorderLayout.NORTH);
            getContentPane().add(table);
            setSize(500,300);
            setVisible(true);
       }
  public static void main(String[]args){
      new AbTab2( );
      }
public void valueChanged(ListSelectionEvent e){
   int min=selectModel.getMinSelectionIndex( );
   int max = selectModel.getMaxSelectionIndex( );
   System.out.println
   ( "Min index selected: " + min  + " Max index selected " + max );

/* pass these index values to the AbstractTableModel getValueAt( ) method
    These values then can be set to another component such as a list       */
  }
}
class CourseModel extends AbstractTableModel{
         String[] colNames;
         Object[][] data;
      CourseModel( ){
      super( );
  colNames=new String[]{"Course_Number",
                            "Course_Name",
                            "Description",
                            "Credits"
                            };

 data=new Object[][]{
 {"100", "Java","Intro","1 credit"},
 {"200", "Java","Foundation Classes","1 credit"},
 {"300", "Java","Advanced","1 credit"},
 {"400", "HTML","General", "1/2 credit"},
 {"500", "SQL","General", "1/2 credit"},
 {"600", "JavaScript","General","1 credit"},
 {"700", "C & C++","General","1 credit"},
 {"800", "XML", "General", "1 credit"},
 {"900", "Networking","Intro","1 credit"},
 {"1000","Linux","Intro","1 credit"}
 };
}
public int getRowCount( ){
  return data.length;
  }
public int getColumnCount( ){
  return data[0].length;
  }
  public Object getValueAt(int row, int column){
  return data[row][column];
  }
// The column model related stuff

public String getColumnName(int column){
  return colNames[column];
  }
public Class getColumnClass(int column){
  return (data[0][column].getClass());
  }
}  

DefaultTableModel

When JTable is used in simpler forms, the extension of
AbstractTableModel, DefaultTableModel, may be used.


Loading a JTable using a DefaultTableModel

import javax.swing.*;         // JTable & JFrame
import javax.swing.table.*;   // DefaultTableModel
import javax.swing.event.*;   // events
import java.awt.*;      // layouts
import java.util.*;           // vectors

class Tabler extends JFrame{
      Tabler(){
         Object[] columnsArray=
            { "First_Name","Last_Name","Phone_Number"};

       Object [][] dataArray={
           {"Bob","Dennis","519 613 2224"},
           {"John", "Doe","465 222 1234"},
           {"Mike", "Xerox","987 234 9878"}
           };

      DefaultTableModel model=new DefaultTableModel(dataArray,columnsArray);
        model.setRowCount(7);
        JTable table=new JTable(model);
        JScrollPane scrolledtable=new JScrollPane(table);

        getContentPane().add(scrolledtable,BorderLayout.CENTER);
        getContentPane().add
        (new JLabel("JTable Example"),BorderLayout.NORTH);
        setSize(500,400);
        setVisible(true);
        }
    public static void main(String[] s){
        new Tabler();
        }
    }

JTable is a powerful visual component that has obvious
applications for providing an interface to data stored in
relational databases.

JTree

Another major component which we do not have time to
look at is JTree. It provides a component representation
of a tree data structure. We leave it to you to look into this
component.



Assignment


No assignment! Good Luck on the exam!