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.*;
class HelloFrame extends JFrame{
JTextArea jt=new JTextArea(s);
|
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. */ |
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");
}
}