Procedural programs have a single order of execution. User interaction
takes place when the program is ready for it.
Event driven programs do not have a single order of execution. The order
of execution depends on the events, normally user interactions such as
selecting a menu item, pressing a button, etc.
Graphical User Interface (GUI) models require an event approach.
The operating system registers the events and sends them to the application,
say Java Virtual Machine. Java maintains the current event queue and processing
events from it.
The AWT provides two conceptual types of events: low-level and semantic.
A low-level event is one which represents a low-level input or window-system occurrence on a visual component on the screen.
For example, a low level event is a key press or a key release, a mouse click, drag, move, or release, and so on.
The low-level event classes defined by the AWT are as follows:
java.util.EventObject
java.awt.AWTEvent
java.awt.event.ComponentEvent
(component resized, moved, etc.)
java.awt.event.FocusEvent
(component got focus, lost focus)
java.awt.event.InputEvent
java.awt.event.KeyEvent
(component got key-press,key-release, etc.)
java.awt.event.MouseEvent
(component got mouse-down, mouse-move, etc.)
java.awt.event.ContainerEvent
java.awt.event.WindowEvent
Semantic events are defined at a higher-level
to encapsulate the semantics (meaning) of a user interface component's
model.
For example,
The semantic event classes defined by the AWT are as follows:
java.util.EventObject
java.awt.AWTEvent
java.awt.event.ActionEvent ("do a command")
java.awt.event.AdjustmentEvent
("value was adjusted")
java.awt.event.ItemEvent
("item state has changed")
java.awt.event.TextEvent
("the value of the text object changed")
Note that these semantic events are not tied to specific screen-based
component classes, but may apply across a set of components which implement
a similar semantic model.
Example,
Case-1
Case-2
An event is propagated from a "Source" object to a "Listener" object by
invoking a method on the listener and passing in the instance of the
event subclass which defines the event type generated.
An Event Source is an object which originates or "fires"
events. The source defines the set of events it emits by providing a set
of methods which are used to register specific listeners for those events.
A Listener is an object that implements a specific EventListener
interface.
An EventListener interface defines one or more methods which
are to be invoked by the event source in response to each specific event
type handled by the interface.
In an AWT program, the event source is typically a GUI component and
the listener is commonly an object (or "adapter", discussed
later) which implements the appropriate listener (or set of listeners)
in order for an application to control the flow/handling of events.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class simpleEvent1 extends Applet
{
Button b1;
// One-time initialization for the applet
public void init() {
b1 = new Button("First Button");
this.add(b1);
// creates one object for button listener
MyButtonListener listB1 = new MyButtonListener();
// adds listB1 as the button listener
b1.addActionListener(listB1);
}
// Draw the applet whenever necessary.
public void paint(Graphics g) {
// The pink oval
g.setColor(Color.yellow);
g.fillOval(10, 50, 330, 100);
}
}
// Defines new class for ActionListener interface, which can be used for buttons and some other GUI componenets
class MyButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event) {
String tmpString = event.getActionCommand();
System.out.println("Button Pressed: " + tmpString);
}
}
The Java runtime passes the event to the corresponding component's processEvent()
method:
protected void processEvent(AWTEvent e)
The processEvent() method determines the type of the event and
passes it on to one of five other methods in the Component class:
void processComponentEvent(ComponentEvent e) void processFocusEvent(FocusEvent e) void processKeyEvent(KeyEvent e) void processMouseEvent(MouseEvent e) void processMouseMotionEvent(MouseEvent e)
(note that all the above methods are protected)
We can register an event listener for the event type with the
component.
Typically, an event listener would perform the required action
for the corresponding event (user interaction).
For example, an event listener for a mouse event must implement methods
for mouse pressed, released, dragged, etc.
An even listener is an object of the corresponding event listener
interface.
The low-level listener interfaces defined by the AWT are as follows:
java.awt.event.ComponentListener java.awt.event.ContainerListener java.awt.event.FocusListener java.awt.event.KeyListener java.awt.event.MouseListener java.awt.event.MouseMotionListener java.awt.event.WindowListener
The semantic listener interfaces defined by the AWT are as follows:
java.awt.event.ActionListener java.awt.event.AdjustmentListener java.awt.event.ItemListener java.awt.event.TextListener
For example,
MouseListener declares these methods,
public abstract void mouseClicked(MouseEvent e) public abstract void mousePressed(MouseEvent e) public abstract void mouseReleased(MouseEvent e) public abstract void mouseEntered(MouseEvent e) public abstract void mouseExited(MouseEvent e)
When a component receives a MouseEvent, its processMouseEvent() method checks the ID of the MouseEvent to determine whether this is a
mouse pressed, mouse released, mouse entered, or mouse exited event.
Then it calls the corresponding method in each registered MouseListener
object.
Example,
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class simpleMouseEvent1 extends Applet
{
// One-time initialization for the applet
public void init() {
MyMouseListener ml = new MyMouseListener();
// adds mouse listener to 'this' applet
this.addMouseListener(ml);
}
// Draw the applet whenever necessary.
public void paint(Graphics g) {
g.setColor(Color.pink);
g.fillOval(10, 50, 330, 100);
}
}
class MyMouseListener implements MouseListener
{
public void mousePressed(MouseEvent e) {
System.out.println("Mouse pressed at: " + e.getX() + " " + e.getY());
}
// We must implement these methods,
// but they don't need to do anything.
public void mouseClicked(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
Inner classes allows classes to be defined in any scope.
In previous releases, Java supported only top-level classes, which must be members of packages.
In JDK1.1 release, the programmer can now define inner classes as members of other classes,
locally within a block of statements, or
(anonymously) within an expression.
Inner classes are normally useful to support the work of the
class in which they nest.
Here is an incomplete class FixedStack which implements a stack, and is willing to enumerate the elements of the stack, from the top down:
public class FixedStack {
Object array[];
int top = 0;
FixedStack(int fixedSizeLimit) {
array = new Object[fixedSizeLimit];
}
public void push(Object item) {
array[top++] = item;
}
public boolean isEmpty() {
return top == 0;
}
// other stack methods go here...
/** This adapter class is defined as part of its target class,
* It is placed alongside the variables it needs to access.
*/
class Enumerator implements java.util.Enumeration {
int count = top;
public boolean hasMoreElements() {
return count > 0;
}
public Object nextElement() {
if (count == 0)
throw new NoSuchElementException("FixedStack");
return array[--count];
}
}
public java.util.Enumeration elements() {
return new Enumerator();
}
}
|
An inner class name is qualified by its enclosing class. In the above
example, the proper name of Enumerator is FixedStack.Enumerator.
In Java, a class's non-static members are able to refer to each other,
and they all take their meaning relative to the current instance this.
Thus, the instance variable array of FixedStack is available
to the instance method push and to the entire body of the inner
class FixedStack.Enumerator.
Just as instance method bodies "know" their current instance
this, the code within any inner class like Enumerator
"knows" its enclosing instance, the instance of the enclosing
class from which variables like array are fetched.
For more examples, see the online documentation for JDK1.1.
JDK 1.1 allows an abbreviated notation for local objects.
A single expression syntax combines the definition of an anonymous
class with the allocation of the instance:
For example,
Enumeration myEnumerate(final Object array[]) {
return new Enumeration() {
int count = 0;
public boolean hasMoreElements()
{ return count < array.length; }
public Object nextElement()
{ return array[count++]; }
};
}
For example,
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class simpleEvent3 extends Applet
{
Button b1;
// One-time initialization for the applet
public void init() {
b1 = new Button("First Button");
this.add(b1);
b1.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("First Button Pressed");
}
}
);
}
// Draw the applet whenever necessary.
public void paint(Graphics g) {
// The pink oval
g.setColor(Color.yellow);
g.fillOval(10, 50, 330, 100);
}
}
The AWT provides a number of adapter classes for the different EventListener
interfaces. These are:
ComponentAdapter
ContainerAdapter
FocusAdapter
KeyAdapter
MouseAdapter
MouseMotionAdapter
WindowAdapter
Each adapter class implements the corresponding interface with a series
of do-nothing methods. For example, MouseListener declares these
five methods:
public abstract void mouseClicked(MouseEvent e) public abstract void mousePressed(MouseEvent e) public abstract void mouseReleased(MouseEvent e) public abstract void mouseEntered(MouseEvent e) public abstract void mouseExited(MouseEvent e)Therefore, MouseAdapter looks like this:
package java.awt.event;
import java.awt.*;
import java.awt.event.*;
public class MouseAdapter implements MouseListener {
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) {}
}
By subclassing MouseAdapter rather than implementing MouseListener
directly, you can avoid having to write the methods you don't actually
need. You only override those that you plan to actually implement.
For example, here's a MouseAdapter that beeps when the mouse is
clicked
import java.awt.*;
import java.awt.event.*;
public class MouseBeeper extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
Toolkit.getDefaultToolkit().beep();
}
}
Without extending the MouseAdpter class, we need to write the same class
like this
import java.awt.*;
import java.awt.event.*;
public class MouseBeeper implements MouseListener {
public void mouseClicked(MouseEvent e) {
Toolkit.getDefaultToolkit().beep();
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
Another Example,
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class simpleMouseEvent3 extends Applet
{
// One-time initialization for the applet
public void init() {
this.addMouseListener(
new MouseAdapter() {
public void mousePressed(MouseEvent e) {
System.out.println("Mouse pressed at: " + e.getX() + " " + e.getY());
}
}
);
}
// Draw the applet whenever necessary. Do some fancy graphics.
public void paint(Graphics g) {
g.setColor(Color.pink);
g.fillOval(10, 50, 330, 100);
}
}