What is distressing for us as non-GUI interface programmers is that the meaning
of "programming" has changed. It is no longer the case that we write everything.
Now we are reduced to writing the code that responds to events along with the
code that decides what events to respond to.
Hence we have to trust that all the other glue will be there when we
need it.
Applets must
Browser Control of Applets: When a browser, analysing a web page,
encounters an <APPLET> tag it looks for the class file mentioned
in the tag. This is loaded accross the network and into the browser.
Next the Applet object is instantiated and init() is invoked. This means
the browser must do something like execute new myApplet() so the default
constructor must exist.
Next the start() method of the Applet is invoked and paint() as well
so that we can actually see the Applet.
The browser is in control. If a mouseClick event occurs it is the browser
that finds out first and informs the Applet. After all, the Applet is occupying
space on the screen reserved for the browser image isn't it?
It is the browser that calls the event listener methods to respond to events.
The browser is busy so to handle all the things going on for an Applet it sets
up a separate control thread for each Applet.
An Applet can go between start() and stop() many times before it is
finished.
An Applet can define none, some or all of the above methods. Click only
defines init().
When you write a normal program you can follow the execution path in your mind
because every bit of executed code (except library funtion calls) is written
by you. Event-driven programs are written completely differently.
Be sure that your event-response methods are short and sweet. Otherwise you
will see slow response times and thing hte program sluggish.
Things that take time like a long calculation or drawing a complicated
picture should be done in a separate thread.
The original Click program can be improved. Instead of just responding to
a mouseClick event we can break the event in two - mousePressed and mouseReleased -
and respond to both of these.
If an Applet needs GUI components - Buttons, TextBoxes, etc - these are
provided by the Java AWT. Window objects are collectively called widgets.
The AWT gives you a single development API regardless of where the Applet
is going to run - X/Motif, Windows or MacOS.
Part of the AWT object hierarchy is:
Not all Components are Containers, etc. Other GUI objects like Buttons
fall elsewhere under the Component hierarchy.
AWT controls the dwaring of all graphical objects. There are three member
methods that draw an applet.
An Applet is a custom component so it needs to provide its own paint() method.
The paint() method draws the display area of the Applet.
Graphical components are normally "contained" in something referred to as a
parent component. The container
component is the component that is aware of the location anddimensions of anything
it contains. Hence it is within the parent component code that we can locate
and resize a contained component.
An Applet's parent is a part of the browser.
In any component, teh upper left-hand corner has coordinatees (0,0).
The current size of the component is determined by calling the two component
methods
Although we call paint() to draw something. Even so, it is the Graphics object
that we pass to paint() that does the actual drawing. Graphics objects
AWT components handle events in a standard way. Since an Applet is a Panel,
which is an AWT component, an Applet can handle certain standard events. Not
all types of components can handle all types of events.
When AWT gets an event it:
It is possible to put the listener code inside the source so you end up with
fewer classes but they are more cluttered.
Just what sorts of event types exist? The following are component events.
The evetn source responds to an event by calling a call-back function
defined as part of the listener. The programmer gets specific event behaviour
by overriding the call-back functions.
To register a listener we use the addXyzListener() method that is part
of the Component class. We pass the listener object as an argument. We
do this at set-up time (in init() of the Applet, for example). The idea
behind registration is for the Applet to ignore events that are not of interest.
It is also possible to removeXyzLister().
Listeners can extend adapters or implement event listener interfaces. There
is typically one call-back method for each event type in the event class.
Whenever a call-back method is invoked it is supplied with ( "sent") an EventObject
by the invoking environment.
For example, the FocusListener has two call-backs.
The AWT Component class supports registration of all component-level
event listeners:
NOTE: AWT makes no promises on the order in which events are delivered to
as set of registered listeners. It is safe for a listener to modify the data
state of an event object without interfering with other listeners receiving the
same event (must by either sequentially executed or monitored).
To make writing listeners easier there are skeletal implementations in known
adapter classes
Event-driven programs sit and wait for events to happen. Applets normally sit around
after initialization and wait.
The sequence in which these methods are invoked is that of the above figure.
////// CLick2.java //////
import java .awt.Graphics;
import java.awt.event;
public class Click2 extends Applet {
public void init() {
addMouseListener(new MouseHandler(this)); // (1)
showStatus("Click2: inititalized");
}
public void start() (
if ( msg == null) msg = " Counting Ups and Downs":
showStatus("Click2: started");
}
public void stop() (
msg = " See you later!":
showStatus("Click2: stopped");
}
public void doUp() {
msg = " Ups = " + ++u + " and Downs = " + d ;
repaint();
}
public void doDown() {
msg = " Ups = " + u + " and Downs = " + ++d
repaint();
}
public void paint(Graphics g) {
g.drawRect(0,0,getSize().width-1,getSize().height-1);
g.drawString(msg,5,30); // draw at location
}
private int u = 0,d = 0;
private String msg = null;
}
class MouseHandler extends MouseAdapter {
MouseHandler(Click2 ap) { app = ap; }
public void mousePressed(MouseEvent e) { app.doDown(); } // overriding
public void mouseReleased(MouseEvent e) { app.doUp(); } // overriding
private Click2 app;
}
public void paint(Graphics g)
public void update(Graphics g)
in response to a request to repaint(). The update() method is
called with a graphics context object that defines the graphics environment.
This object knows things like the current foreground colour, etc. update()
works by clearing the component display area and then invoking paint().
getSize().width // component width in pixels
getSize().height // component height in pixels
paint() is requested automatically after start(). After that, it is requested,
via update() by calling repaint().
Coordinates in computer graphics are pixel counts. (0,0) is the upper left-hand
corner of the drawing surface. X increases to the right and Y down the screen.
Your application must build its own listeners and register them with sources.
The following are semantic events.
void focusGained(FocusEvent)
void focusLost(FocusEvent)
To handle events by implementing a listener interface you need to code
class ActionHandler implements ActionListener {
ActionHandler(ClientClass cl) {
client = cl; // save local reference to client
}
private ClientClass client;
public void actionPerformed(ActionEvent e) {
// action handling code here such as
// clinet.doAction();
}
}
actionPerformed is the call-back method. This is the method invoked
(scheduled) by the event source.
addEventTypeListener(EventTypeListener el)
removeEventTypeListener(EventTypeListener el)
AWT event sources support event multicasting; ie, sending an event to
multiple sources.
addComponentListener(ComponentListener )
addFocusListener(FocusListener )
addKeyListener(keyListener )
addMouseListener(MouseListener )
addMouseMotionListener(MouseMotionListener )
High-level components such as a
Button or List call also fire semantic
events by invoking
actionPerformed
itemStateChanged
found in the ActionListener and ItemListener spec.
ComponentAdapter
FocusAdapter
KeyAdapter
MouseAdapter
MouseMotionAdapter
WindowAdapter
All these adapters implement corresponding listeners by implementing "do-nothing"
methods. You can subclass an adapter and implement just the methods you need.
All the other methods are invoked when the events that don't interest you occur
but since they "do nothing" it appears as though the event was not responded to.
pletch@cs.newpaltz.edu