A Simple Intro to Swing          Peter Komisar

                                                                                                                                minor revision: Jan 30, 2001


The swing collection of components is introduced at this point for a number of reasons.
The first is they provide an easy to understand, and clear picture of how Java works.
The different class members we talked about in the previous section are used in building
visual components as much as in other areas of programming in Java. Here we will see
classes, objects of classes, fields, constructors and methods all being used. The second
reason to introduce swing components at this point is so you will be familiar with them
so you can get started using them in a programming project.


awt and swing are major packages used in  Java to build Graphical User Interfaces.
Both are parts of a larger grouping called the Java Foundation Classes. (JFCs)
They contain the components needed to build the GUIs  for your programs. The
designers offer simple and convenient methods for using these components that are
often described in a chapter in Java texts. To use the full capabilities of the swing
a study has to be made of how the components are composed to combine data
and the presentation or view of the data to the user. This explains why you can
1000 plus page books dealing with nothing but the details of swing.

The graphical user interface allows you to interface your program's contents to it's
user through visual components. Visual components can also help to cut down on
the amount code you need to generate. For instance a checkbox component can
replace the need for code to make selections.In Java you have the legacy package,
the Abstract Windowing Toolkit, most often called AWT, at your disposal. You
now also have the more elaborate and capable swing Components. The AWT
components are in the java.awt package and the swing widgets are in javax.swing.

Java 1.2 incorporated the new collection of graphical components called swing.
(Before this version they were contained in an extension package hence the x in javax.)
The collection derives from the Internet Foundation Classes originally developed
by Netscape. Sun acquired the IFCs. Swing components solve some nagging problems
which remained with the original awt components which prevented them from appearing
exactly correctly when they were ported across different platforms. Also swing brings
some new features to java's visual interfaces like the ability to add small pictures or
icons to the components.

If you know your awt components you can easily obtain the corresponding swing
component by prefixing a J to the name of the awt component. JLabel is the swing
equivalent of Label in awt.JFrame is the swing equivalent for Frame in awt. In
addition, swing adds many new components not found in awt.


Applets, Stand Alone Applications & Servlets

In Java, there are a number of forms you can use to house your programs. You might
write a stand-alone application that runs on your PC. You can run an applet that
resides in an HTML page and is started when the page is opened in a browser. You
can also write java programs for servers, in java classes called servlets, which facilitate
programming the kinds of things you typically need to do on a server, and particularly
the services you would provide using the HTTP protocol. A fourth type of program is
the enterprise java bean. It serves to interface programs like servlets to 'back-end'
databases. The server-side servlet and enterprise javabean do not really need user
interfaces, but the stand-alone application will benefit from having a Graphical User
Interface (GUI ). The Applet and their JApplet counterpart are naturally graphical as
they are themselves visual components which are part of awt and swing respectively.


A Tour of Common Components

We can begin by taking a cursory look at a several components. Then we can build an
example employing them all.

JFrame

JFrame is the standard component used to contain all the other sub-components that
make up your graphical user interface. It is a more complicated component than it's awt
predecessor, Frame. The swing designers added several layers to allow for the addition
of components like tooltips and pop-up menus. Normally JFrame is subclassed to
create your own frame to hang other components in. First,  JFrame and other swing
component are made readily available to your program using the import statement at
the top of your source code.This statement sets up a local path to the package you wish
to access.

import javax.swing.*;         // for awt the statement is import java.awt.*;

class myFrame extends JFrame{

//  many other sub-components will likely be added to the frame . . .

JFrame is a top level container and has some requirements that other swing components
don't have. It is not automatically visible and doesn't have an initial size.  JFrame requires
the following two methods as exampled by the following.

setSize(300,300);         // the 300 numbers refer to a width and height of three hundred pixels.
setVisible(true);
 
 
HelloPlanet in a JFrame


//  Here the properties of a text area and the text added to it are being set

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

 class HelloFrame extends JFrame{
  public static void main(String[] args){
    HelloFrame hello=new HelloFrame();
    String s=
      new String(" \n Hello Planet! \n\n\n (in a text area, in a frame.)");
 

    JTextArea jt=new JTextArea(s);
    jt.setBackground(new Color(255,240,220));
    jt.setForeground(Color.blue);
    jt.setFont(new Font("Helvitica",Font.BOLD,20));
    hello.getContentPane().add(jt);
    hello.setSize(400,200);
    hello.setVisible(true);
   }
 }

There is some exotic code (called the anonymous inner class,) which can be used to close
the window. This device is a nifty implementation of a WindowListener interface which
specifies a number of stock methods to work with frames including the windowClosing( )
method.We'll add this window closing code to our final example.

JFrame has alternate controls that close the window. In earlier Java versions, these did
not close the underlying operating system process. You would close the DOS process
with Ctrl-C. This is fixed in Java 1.3, where the method setDefaultCloseOperation( )
can be used, in conjunction with constants like, EXIT_ON_CLOSE, to close the frame.

 JFrame has a complicated layered architecture. This was neccessary to facilate features
layering of components, drag and drop and to enable the setting tooltips. This results in
an added step that must be followed that wasn't required when using awt's Frame. When
you add a component to the JFrame subclass via an add( ) method, you have to call the
content pane first. The content pane is what you add your sub-components to. This
amounts to adding the method, getContentPane( )'in line' with the add( ) method. For
example,

getContentPane( ).add(mySubComponent);

// This will be made clearer by examples that follow. 


A Brief Note on Layout Managers

Components that serve as containers for other components, have predefined behaviour
in how they place their contents. This layout policy is dictated by layout manager. There
are a number of these invisible layout managers. Several components have a layout
manager assigned to them by default. The commonest and easiest to use are
BorderLayout, GridLayout and FlowLayout.

(A new swing layout BoxLayout is pretty handy and worth investigating. There is also
 a CardLayout that has been effectively replaced by the component JTabbedPane.
 Another layout manager which is both flexible and difficult is GridBagLayout which
 you can experiment with.)

BorderLayout has an EAST, WEST, NORTH, SOUTH  and CENTER region defined.
GridLayout divides your component into a grid of evenly sized squares. FlowLayout adds
things from left to right, top to bottom, centering as it goes. JFrame has a BorderLayout
manager by default. You can easily change a component's layout using the setLayout( )
method which takes an instance of the new type of layout as an argument.

See Layout Managers for more details. The point of this brief note is to make you aware
there are invisible layout manager classes that are taking care of how the components you
add are being positioned in the the presentation.


JPanel

BorderLayout will only allow you to add a single component to each of it's regions.
What if you want a keyboard layout made up off 101 buttons at the bottom of your GUI ?
To the rescue comes JPanel. JPanel is the all purpose sub-panel for adding and creating
sub-consoles. Sets of JPanels can be nested in other JPanels which may be finally added
to an area of a JFrame. JPanel has a FlowLayout manager by default.

JPanel  jpanel = new JPanel( );

// a declaration, assignment and instantiation of a JPanel using a no-arg constructor.

JLabel

Like JPanel, JLabel is a simple component which is used to label your interface. In it's
simplest form the class is built with a no-args constructor which you can set text to at
a later point in the program. It is common to see the text provided as a String literal at
the time the class is  instantiated. Other JLabel constructors take icons and positioning
instructions but for now we example the commonest form.

JLabel jlabel = new JLabel ("a label");

// here the constructor that takes a String object

JTextField

JTextField is an editable area that allows the entry of a string of characters represented
in Java as a String object. The string can be set from the keyboard or via the setText( )
method. JTextField, like many other components fire an event object when their controls
are activated. For instance, pressing Enter while the cursor is focused on a text field
generates an action event. These events are processed by event-handling classes
called listeners. Listeners are used by the programmer to provide appropriate
responses to the activation of a specific component. // more on events below.

JTextField jf = new JTextField( "Text to start", 12);

// This creates a textfield with starting text and 12 columns.

JTextArea

JTextArea is like a JTextField but more sophisticated. It can act like a mini text editor.
It can be made editable or non-editable. JTextArea is often used to input and display
comments. The number of rows and columns can be specified at the time of it's creation.

JTextArea jt = new JTextArea("Some Text", 5, 5 );

// This creates a text area object with some starting text and an area set to 5 rows and 5 columns.

JList

JList is a component that on the surface seems to be simple however a detailed study
shows it is a complicated component. It has constructors that allow it to be built with
an array of Objects, a Vector or a ListModel. (The Vector is a container class that
can store different types of objects and a ListModel is a special Java class that is used
to represent the data that is viewed in a JList.) Here we example the use of an array
of Object type. The contents of this array are really objects of the String class that can
be represented by the root parent class, Object.

Object[] countries=new Object[]{" ",
  "Some of the countries of the world in alphabetical order", " ",
  "Arabia","Borneo","Canada","Denmark","England","France","Holland",
  "Korea","Malaysia","Nepal","Paraguay","Sweden","Uraguay"};

JList jl= new JList(countries);


We'll take an break here to show how these components can be added to a panel

JPanel jp = new JPanel( );    // First a JPanel is created.
jp.setLayout(new GridLayout(6,1));  // sets a grid of  6 rows and 1 column
 // each component is built and added  to the JPanel instance.
JLabel label1=new JLabel("Country");
JLabel label2=new JLabel("Government");
JLabel label3=new JLabel("Language");

JTextField field1=new JTextField("France");
JTextField field2=new JTextField("Democracy");
JTextField field3=new JTextField("French");

// Here the third text field has some extra stuff done
// It is made uneditable and has it's foreground and background color changed

field3.setEditable(false);
field3.setBackground(Color.blue);
field3.setForeground(Color.white);

// grid layout adds the items in order to the grid, top to botton

jp.add(label1);
jp.add(field1);
jp.add(label2);
jp.add(field2);
jp.add(label3);
jp.add(field3);

// Now the panel is loaded and can be added to the north region of the border layout of the JFrame class.

getContentPane( ).add(jp, BorderLayout.NORTH);



 
 More on Swing


 In order to keep the discussion simple I have avoided mentioning that a miniature picture 
 called an Icon can be added to most swing components. The easy way to do this is to create 
 an  ImageIcon class object where the picture you want iconified is provided as an argument 
 to the constructor. 

 Icon ii =new ImageIcon("someImage.jpg"); // will also take a .gif file

 This image is then added to the constructor of the component.

 JButton jb = new JButton(" button with Icon ", ii ); 
.

JButton

JButton is the commonest and most popular component to cause something to happen
in an event-driven program. A label can be added with the constructor or after via a
method call. A JButton creates an action event which if listened for by a listener class can
take care of doing a particular action each time the button is pushed. There are a number
of swing components that are essentially variations on the button theme, like JCheckbox,
JRadioBox and JMenuItem.

JToolTip

One of the reason JFrame was made more sophisticated was to add a transparent layer
on which tooltips and pop-up menus could be placed. To set a tooltip for a component
simply requires a method call on the target component. For example,

JButton jaybutton = new JButton(" Jay Button " );
jaybutton.setToolTipText(" Press this to see a Blue Jay ");

JScrollPane

In awt, scroll panes added automatically as needed. In swing for the sake of flexibility,
a JScrollPane instance is created and the component that you wish to scroll is added to
the constructor as an argument.

//using the JList reference from above, it becomes an argument to the JScrollPane constructor.

JScrollPane jsp=new JScrollPane(jl);
getContentPane().add(jsp);


A Little on Events

When a component like a button is activated an event object is created. In the
case of JButton an ActionEvent is created.. Classes become listeners for events
by implementing listener interfaces. This amounts to tagging to the class name the
implements keyword followed by one of the listener interfaces. The listener you need
to listen for ActionEvent objects is an ActionListener (the naming pattern is not
accidental). When a class implements an interface it  takes on the responsibility
of providing implementations for the abstract methods listed in the given listener
interface. (This is boils down to providing bodies for the list of methods. This can be a
simple as providing a method signature with a pair of empty curly braces.) So in the case
of a button, the enclosing class can become the listener by implementing the ActionListener
interface. The component that creates the event has to register the listener via an
addEventListener method. In the case of the button the addActionListener method
is used.

Example

import java.awt.*;
import java.awt.event.*;
import  javax.swing.*;
 
A button in a frame. A listener class provides the response to the button's activation

class Top_Class extends JFrame {
public static void main(String[] args){
  ListenerClass lc= new ListenerClass();
  JButton jb= new JButton("Source" );
  jb.addActionListener(lc);
  Top_Class tc=new Top_Class();
  tc.getContentPane().add(jb);
  tc.setSize(400,200);
  tc.setVisible(true);
  }
}
class ListenerClass implements ActionListener{
  public void actionPerformed(ActionEvent ae){
  System.out.println
("This is the action performed when the button is pushed"); 
    }
}
 /* This style is ok for making things happen outside the program like writing to a file or 
   signalling a printer however for communicating between objects within a program it is 
   better to make the container of the components the common listener for events  created. */ 



There are many other classes in the swing package and a lot more detail as what can be
done. If you have van der Linden's 'Just Java' read Chapter 18 and 19 for a more detailed
survey or check the swing tutorial by the Magelang Institute available at the Sun web site.

Code Sample

The following  code example summarizes what we looked at and throws a few
extra things in as well. A modification of this program is also provided to show
how a text field's contents can be add to the JList. JList offers the ability to treat
the data it renders as a list. If all you need is to display text, a JTextArea might
be a easier and more appropriate component to use.


import javax.swing.*;    // brings in the swing components
import java.awt.*;        // needed for layouts like GridLayout
import java.awt.event.*;   // this brings in the classes and interfaces that deal with events

// note the class implements the ActionListener interface

class SwingFrame extends JFrame implements ActionListener{

/*  notice a lot of the code's components are contained in the Constructor. these will be out  of scope
    for class member method calls. I moved the text field declarations to the head of the program into
    the class namespace so that the variables would be referencable  from the class  methods namely
    the actionPerformed method which resets the texts of the text fields.                                                    */

JTextField field1;
JTextField field2;
JTextField field3;
 

  SwingFrame(String s){
    super(s);

     // it is unlikely we will reference the labels so we can hide them in the scope of the constructor

    JLabel label1;
    JLabel label2;
    JLabel label3;

    JPanel jp = new JPanel( );    // First a JPanel is created.
      jp.setBackground(Color.white);
      jp.setForeground(Color.yellow);
      jp.setLayout(new GridLayout(3,2));   // this sets the layout to 3 rows and 2 column
      label1=new JLabel("Country",0); // Now each component is built and added to the JPanel
      label2=new JLabel("Government",0);
      label3=new JLabel("Language",0);

      field1=new JTextField("France");
      field1.setBackground(Color.black);
      field1.setForeground(Color.white);
      field2=new JTextField("Democracy");
      field3=new JTextField("French");
      field3.setEditable(false);               // change this to true to return to editable
      field3.setBackground(Color.blue);
      field3.setForeground(Color.white);

      jp.add(label1);
      jp.add(field1);
      jp.add(label2);
      jp.add(field2);
      jp.add(label3);
      jp.add(field3);

// Now the panel is loaded and can be added to the north
// region of the border layout of the JFrame class.

      getContentPane( ).add(jp,BorderLayout.NORTH);

// this array creation expression creates an array of Object type in which a set of String elements
// are stored. If the the list needs to be changed a Vector would be a better choice than an array. A
// Vector is a storage container like an array however it can change size and has methods that make
// adding and removing elements easy

   Object[] countries=new Object[]{" ",
       "Some of the countries of the world in alphabetical order", " ",
       "Arabia","Borneo","Canada","Denmark","England","France","Holland",
       "Korea","Malaysia","Nepal","Paraguay","Sweden","Uraguay"
        };

// Here a JList object is added to a JScrollPane which in turn is added to the center region of BorderLayout

      JList jl= new JList(countries);
      JScrollPane jsp=new JScrollPane(jl);
      getContentPane().add(jsp);

// the default version of  add is to the center region.
// This version has the same effect as getContentPane( ).add(jsp, CENTER);

// To the south region a JButton instance is added with a tooltip associated with it

      JButton jbS=new JButton("Add a Country");
      jbS.setToolTipText(" Press this to add a new country ");
      jbS.addActionListener(this);       // the listener, here the container, is added to the button
      getContentPane( ).add(jbS,BorderLayout.SOUTH);

      setSize(400,400);  //  width and height of 400 hundred pixels
      setVisible(true);

// Here's the code that will exit the process you are running in when the window is closed.
// We do this from within  one of java's most exotic code features called an anonymous inner class.
// For now lets just  use it.

                  addWindowListener(new WindowAdapter( ){
                  public void windowClosing(WindowEvent e){
                  System.exit(0);
                  }
               });
}
 

// This is the method defined in the ActionListener interface. By implementing this interface
// this class takes on the responsibility of providing an implementation for it's method(s) which
// follows here. The method puts a message to console and sets the text in the text fields
// indicating this is a demo and not a fully functional program

public void actionPerformed(ActionEvent ae){
System.out.println("Here's the action outputed to console");
field1.setText("This demo ");
field2.setText("is just a show");
field3.setText("of swing widgets");
}

/*  the main( ) method begins in which an instance of the  class is created.  Here all the code to build
     the GUI was in the big constructor. The other class members are the main method, the actionPerformed
    method and the reference variables defined in class scope at the top of the program.                   */

    public static void main(String args[]){
       SwingFrame sf=new SwingFrame("Countries of the World");
       }
   }