Programming User Interfaces using the AWT (and the JFC)
Jan Newmarch jan@newmarch.name
Last modified: 10 February, 1998.
These slides are Copyright Jan Newmarch, 1995, 1996, 1997, 1998.
Abstract
This tutorial discusses using the AWT (Abstract Window Toolkit)
of Java
to perform platform-independent GUI programming.
It makes the following
assumptions:
- Exposure to Java
- Exposure to OO programming
- Familiarity with a GUI library such as Motif
Contents
GENERAL CONCEPTS
GUI programming with Java
- Java provides a set of user interface components
- The set is the same across Unix, Windows and the Macintosh
- The user interface components can be used for applets and for
applications
- The set allows cross-platform applications and applets to be built
Evolution of Java GUI programming
- The AWT (Abstract Window Toolkit) has been present in all versions
of Java
- The AWT objects are built above native code objects, giving a native
look-and-feel
- The AWT objects are a least common denominator of all platforms
- The Swing objects are a separate library for JDK 1.1
- The Swing objects are in pure Java, and have the same look-and-feel
on all platforms
- The L&F of Swing objects can be customised to particular styles
- In JDK 1.2, the Swing objects are part of the Java Foundation Classes
- The JFC objects will provide a superset of each platform's objects
- The AWT objects will decrease in importance over time
Applet vs Application
-
An application starts from
main()
in a subclass of Frame
-
An applet has as toplevel a subclass of Applet, using methods
-
Placing initialisation code in the constructors makes it relatively
easy to write applets and applications sharing code.
AWT Hierarchy
-
``Primitive'' objects are directly derived from Component
-
LayoutManager is used for geometry management
-
LayoutManager2 fixes some deficiencies in LayoutManager
(from JDK 1.1 on)
-
AWTEvent encodes all the event information
-
ComponentPeer objects are used to give the native implementation, and should be
ignored most of the time
AWT Primitive Components
The main ``primitive'' objects derived from Component are
These are all in package java.awt.
Swing Primitive Components
These mirror the AWT components:
- There are additional components as well
- In general, to each AWT component is a Swing component
- As much as possible, each Swing component has the
same methods
and behaviour as its corresponding AWT component
Container Components
Container objects are derived from Component. The main ones derived from that
are
-
Dialog
-
FileDialog
-
Frame
-
Panel
-
Window
MenuComponents
Menus are implemented by subclassing MenuComponent which is derived from Object
-
CheckboxMenuItem
-
Menu
-
MenuBar
-
MenuItem
Layout Objects
Layout objects derive from Object and are used for geometry management
-
BorderLayout
-
CardLayout
-
FlowLayout
-
GridLayout
-
GridBagLayout
COMPONENTS
Component Objects
-
Component has a number of methods inherited by all objects derived from it.
-
Some methods set state
-
setEnabled() (replaces enable()/disable())
-
setVisible() (replaces hide()/show())
-
setBackground(Color)
-
setFont(Font)
-
Other methods are informational
-
boolean isEnabled()
-
boolean isShowing()
-
Color getBackground()
-
Other methods are behavioural - see later
Label
Label (2)
Hello World
Hello World using a Label in a Frame is
import java.awt.*;
public class Hello extends Frame {
public static void main(String argv[])
{
new Hello();
}
Hello() {
Label hello =
new Label("Hello World");
add(hello, "Center");
setSize(200, 200);
setVisible(true);
}
}
JLabel
- JLabel is the Swing counterpart to Label
- It does almost the same as Label (newline shown
as VT)
- It can show a string and/or image
- Just replace Label by JLabel throughout
Frame
JFrame
- JFrame is the Swing equivalent of Frame
- It adds double buffering to avoid flickering
during drawing
- It has a slightly different interface to
geometry management
Hello World using Swing
import com.sun.java.swing.*;
public class JHello extends JFrame {
public static void main(String argv[])
{
new JHello();
}
public JHello() {
JLabel hello =
new JLabel("Hello World");
getContentPane().add(hello, "Center");
setSize(200, 200);
setVisible(true);
}
}
Button
JButton
- JButton is the Swing equivalent of Button
- A JButton can show a string and/or image
- There is much extended control and behaviour
- set/getLabel() has been replaced by set/getText()
EVENTS
AWT events
-
Event model in Java 1.0 is poor s/w engineering, based on
class
Event
-
In Java 1.1 it changes to a new model called delegation,
based on class
AWTEvent
- This event model is unchanged for Java 1.2
-
Events are handled by listeners,
not by subclasses of GUI objects
AWT Event classes
The class AWTEvent has subclasses:
-
ComponentEvent
-
FocusEvent
-
KeyEvent
-
MouseEvent
-
WindowEvent
-
ActionEvent
-
AdjustmentEvent
-
ItemEvent
AWT Event ids
Some of these classes have an id
value to distinguish between them
-
KeyEvent: KEY_PRESSED, KEY_RELEASED, KEY_TYPED
-
ComponentEvent: COMPONENT_MOVED, COMPONENT_RESIZED, COMPONENT_SHOWN,
COMPONENT_HIDDEN
-
MouseEvent: MOUSE_CLICKED, MOUSE_DRAGGED, MOUSE_PRESSED, etc
Triggering events
Events are posted by user actions (or may be done programmatically)
-
ActionEvent
-
click on Button
-
double-click on List item
-
click on MenuItem
-
press <enter> key in TextField
-
ItemEvent
-
select an item in a Choice box
-
Checkbox
-
select or deselect a List item
Listeners
Listeners are objects that handle events (not the GUI Components
any more)
-
ActionEvent handled by ActionListener
-
KeyEvent handled by KeyListener
-
Mouse motion events handled by MouseMotionListener (optimisation)
-
Other Mouse events handled by MouseListener
Listeners as interfaces
Listeners are defined as interfaces and must be implemented by the
application
public interface ActionListener
extends EventListener {
public void actionPerformed(ActionEvent e);
}
public interface MouseListener
extends EventListener {
public void mouseClicked(MouseEvent e);
public void mousePressed(MouseEvent e);
public void mouseReleased(MouseEvent e);
public void mouseEntered(MouseEvent e);
public void mouseExited(MouseEvent e);
}
Registering listeners
-
Each GUI object generates certain events
-
For each class of AWTEvent there is an add<Event>Listener
-
e.g.
For Button, List, MenuItem and TextField there is a method
addActionListener()
-
e.g.
For Choice Checkbox and List there is a method
addItemListener()
Simple Delegation program (1)
import java.awt.Button;
import java.awt.Label;
import java.awt.Frame;
import java.awt.event.ActionListener;
public class DelegateDemo extends Frame {
public static void main(String argv[]) {
new DelegateDemo().setVisible(true);
}
public DelegateDemo() {
// create the GUI objects
Button left = new Button("Left");
Button right = new Button("Right");
Label label = new Label(" ", Label.CENTER);
// set their geometry
add(left, "West");
add(right, "East");
add(label, "Center");
pack();
// create a listener and add it to each Button
SimpleListener simple =
new SimpleListener(label);
left.addActionListener(simple);
right.addActionListener(simple);
}
}
/**
* A listener object that is invoked when a Button is activated
* It finds the Button's label and sets it in a Label
*/
class SimpleListener implements ActionListener {
private Label label;
public SimpleListener(Label l) {
// the listener needs to know the Label it will act on
label = l;
}
public void actionPerformed(java.awt.event.ActionEvent e) {
// get the label showing in whichever Button was pressed
String name = e.getActionCommand();
// set this in the Label object
label.setText(name);
}
}
Some variations
- The Frame is often used as a listener for all components.
This is probably bad practice if done too much
- Inner classes are contained within a class, and are
visible only within that class. Using an inner class
for a listener can sometimes be tidier
- Anonymous classes can be used as listeners, at the
expense of readability
Motion Tracking (1)
Motion Tracking (2)
import java.awt.*;
public class TrackResize extends Frame {
public static void main(String argv[]) {
new TrackResize().setVisible(true);
}
public TrackResize() {
Label label = new Label();
add(label);
setSize(300, 100);
addComponentListener(new Tracker(label));
}
}
class Tracker implements ComponentListener {
private Label label;
Tracker(Label l) {
label = l;
}
public void componentHidden(ComponentEvent e) {
// empty
}
public void componentMoved(ComponentEvent e) {
showGeometry(e);
}
public void componentResized(ComponentEvent e) {
showGeometry(e);
}
// Tracker continues
public void componentShown(ComponentEvent e) {
// empty
}
private void showGeometry(ComponentEvent e) {
Component c = e.getComponent();
Dimension d = c.getSize();
Point p = c.getLocation();
label.setText("Position: (" + p.x +
"," + p.y + ") Size: )" +
d.width + "," + d.height + ")");
}
}
Changing key values (1)
import java.awt.*;
import java.awt.event.*;
public class MapKey extends Frame {
public static void main(String argv[]) {
new MapKey().setVisible(true);
}
public MapKey() {
TextField text = new TextField(20);
add(text);
pack();
text.addKeyListener(new ToUpper());
}
}
Changing key values (2)
class ToUpper implements KeyListener {
public void keyTyped(KeyEvent e) {
// empty
}
public void keyPressed(KeyEvent e) {
e.setModifiers(Event.SHIFT_MASK);
}
public void keyReleased(KeyEvent e) {
// empty
}
}
Consuming events
-
Events may need to be ``blocked'' from reaching objects sometimes
-
In password entry, keystrokes need to be caught by the application
but not reach the Text object for display
-
A GUI builder might use mouse clicks to select objects such as
Button, but not activate the Button
-
The delegation model allows this for key and mouse events
-
Events are discarded by calling the method
AWTEvent.consume()
Consuming events
This key listener discards non-alphabetic events:
public class Alpha implements KeyListener {
public void keyPressed(KeyEvent e) {
if (! Character.isLetter(e.getKeyChar())) {
Toolkit.getDefaultToolkit().beep();
e.consume();
}
}
public void keyReleased(KeyEvent e) {
// empty
}
public void keyTyped(KeyEvent e) {
// empty
}
}
Generating Events
-
Events may be created and placed on the event queue for applications
-
The event queue is found from
Toolkit.getDefaultToolkit().getSystemEventQueue()
-
The event queue is not accessible yet from applets (need applet queue)
-
Adding semantic events to queue does nothing to native GUI objects,
and only makes the application state inconsistent
-
Adding input events has no effect as yet, but may in the future
-
Adding new event types to the queue may be done
Generating Events of a new Class
-
New event classes can be subclassed from
AWTEvent
-
Possible values for
id
field must be greater than
AWTEvent.RESERVED_MAX_ID
or event handling breaks
-
A subclass of
Component
must be defined to handle the new event type
-
The subclass will ignore events by default: make it receive the new
event by
enableEvents(0)
FileDialog
-
Implemented by Motif FileSelectionDialog
-
FileDialog has two constructors
FileDialog(Frame parent, String title);
FileDialog(Frame parent, String title,
int mode);
-
The mode can be LOAD or SAVE - which affects the labelling of the dialog
-
Major methods are
setDirectory(String) // sets dirMask
setFile(String)
setFilenameFilter(FilenameFilter) - still does nothing
FileDialog (2)
FileDialog Parent
Creation of a FileDialog requires a Frame parent. If this is done from
a Button then the Frame has to be found by walking up
the parent tree from the Button:
class FileOpen implements ActionListener {
public void actionPerformed(ActionEvent e) {
Object fr = e.getSource();
while (fr != null &&
!(fr instanceof Frame))
fr = ((Component)
fr).getParent();
new FileDialog((Frame) fr, "Open");
// etc
}
}
JFileChooser
- JFileChooser is the Swing alternative
All material on this site is under the copyright restriction and
permissions of the Open Content license,
http://www.opencontent.org/opl.shtml