Transcript Unit 15

Unit 15: Component programming
and Graphical User Interface
syllabus
Component
programming
Listening to events
GUI components
Containers
Layout Managers
Event Handling In GUI components
Inner and Anonymous Classes
basic
programming
concepts
object oriented
programming
topics in
computer
science
Component Programming

Component programming facilitates reuse of code

Developing an application becomes like building
something with LEGO blocks: there are a lot of
software components (blocks) and we combine
them together into an application
2
unit 15
Components

A component is a software element

It is an object in the regular OOP sense

It has some additional features:
• methods and properties like a regular object
• graphical view, describing the way the properties
are visualized
• events by which it can communicate with other
components
3
unit 15
Events

Components communicate via events

If component A wants to tell component B that something
has happened to it, it fires an event aimed at component B

The event is an object that encapsulates the information
that A wants to pass to B

There can be many types of events for different types of
information - the type of the event is its class
4
unit 15
Events

For each type of event there should be:
• a suitable event class derived from java.util.EventObject
• an interface for listening to events of this type derived from
java.util.EventListener

A component that is the source of some event (observable
object) maintains a list of registered listeners, and notifies them
when the event occurs

The component which responds to events (a listener) should
implement the listening interface

The observable has a pair of methods for adding and removing
listeners; the listener calls the add/remove methods
5
unit 15
instance of
AlarmClock
collection of
AlarmListeners
addAlarmListener
(AlarmListener l)
removeAlarmListener
(AlarmListener l)
instance of
InterestedClassA
implements AlarmListener
alarmActivated
(AlramEvent e)
addAlarmListener
(AlarmListener l)
implements AlarmListener {
instanceInterestedClassA
of
// ...
AlarmClock
someMethod(AlarmClock a) {
removeAlarmListener
collection of a.addAlarmListener(this);
(AlarmListener l)
}
AlarmListeners
// …
void alarmActivated(AlarmEvent e) {
// do something when an alarm occurs
}
}
instance of
InterestedClassA
implements AlarmListener
alarmActivated
(AlramEvent e)
instance of
AlarmClock
collection of
AlarmListeners
addAlarmListener
(AlarmListener l)
removeAlarmListener
(AlarmListener l)
instance of
InterestedClassA
implements AlarmListener
alarmActivated
(AlramEvent e)
instance of
AlarmClock
collection of
AlarmListeners
addAlarmListener
(AlarmListener l)
removeAlarmListener
(AlarmListener l)
instance of
InterestedClassA
implements AlarmListener
alarmActivated
(AlramEvent e)
instance of
AlarmClock
collection of
AlarmListeners
addAlarmListener
(AlarmListener l)
removeAlarmListener
(AlarmListener l)
addAlarmListener
(AlarmListener l)
instance of
AlarmClock
collection of
AlarmListeners
removeAlarmListener
(AlarmListener l)
instance of
InterestedClassB
implements AlarmListener
alarmActivated
(AlramEvent e)
addAlarmListener
implements AlarmListener {
instance InterestedClassB
of
// ...
AlarmClock
(AlarmListener l)
aMethodInThisClass() {
AlarmClockremoveAlarmListener
a =
collection of
AlarmUtilities.getAlarmClock();
(AlarmListener l)
AlarmListeners
a.addAlarmListener(this);
}
// ...
void alarmActivated(AlarmEvent e) {
// do what needs to be done with the alarm
}
}
instance of
InterestedClassB
implements AlarmListener
alarmActivated
(AlramEvent e)
addAlarmListener
(AlarmListener l)
instance of
AlarmClock
collection of
AlarmListeners
removeAlarmListener
(AlarmListener l)
instance of
InterestedClassB
implements AlarmListener
alarmActivated
(AlramEvent e)
addAlarmListener
(AlarmListener l)
instance of
AlarmClock
collection of
AlarmListeners
removeAlarmListener
(AlarmListener l)
instance of
InterestedClassB
implements AlarmListener
alarmActivated
(AlramEvent e)
instance of
AlarmClock
collection of
AlarmListeners
addAlarmListener
(AlarmListener l)
removeAlarmListener
(AlarmListener l)
instance of
AlarmClock
collection of
AlarmListeners
addAlarmListener
(AlarmListener l)
removeAlarmListener
(AlarmListener l)
instance of
AlarmClock
addAlarmListener
(AlarmListener l)
Alarm EventremoveAlarmListener
collection of
AlarmListeners
(AlarmListener l)
addAlarmListener
(AlarmListener l)
instance of
AlarmClock
Alarm EventremoveAlarmListener
collection of
(AlarmListener
AlarmListeners class AlarmClock
{
l)
//...
void notifyListeners(AlarmEvent e) {
for each AlarmListener l in collection:
l.alarmActivated(e);
}
//..
}
addAlarmListener
(AlarmListener l)
instance of
AlarmClock
Alarm EventremoveAlarmListener
collection of
(AlarmListener
AlarmListeners class AlarmClock
{
l)
//...
void notifyListeners(AlarmEvent e) {
for each AlarmListener l in collection:
l.alarmActivated(e);
}
//..
}
alarmActivated()
instance of
AlarmClock
addAlarmListener
InterestedClassA
implements AlarmListener
{
(AlarmListener
l)
// ...
someMethod(AlarmClock a) {
Alarm
Event
removeAlarmListener
a.addAlarmListener(this);
collection of
(AlarmListener l)
AlarmListeners }
class AlarmClock {
// …
//...
void
alarmActivated(AlarmEvent
e) { e) {
void
notifyListeners(AlarmEvent
// do
when an alarm
forsomething
each AlarmListener
l inoccurs
collection:
}
l.alarmActivated(e);
}
}
//..
}
addAlarmListener
(AlarmListener l)
instance of
AlarmClock
Alarm EventremoveAlarmListener
collection of
(AlarmListener
AlarmListeners class AlarmClock
{
l)
//...
void notifyListeners(AlarmEvent e) {
for each AlarmListener l in collection:
l.alarmActivated(e);
}
//..
}
addAlarmListener
(AlarmListener l)
instance of
AlarmClock
Alarm EventremoveAlarmListener
collection of
(AlarmListener
AlarmListeners class AlarmClock
{
l)
//...
void notifyListeners(AlarmEvent e) {
for each AlarmListener l in collection:
l.alarmActivated(e);
}
//..
}
alarmActivated()
addAlarmListener
(AlarmListener l)
instance of
AlarmClock
Alarm EventremoveAlarmListener
collection of
(AlarmListener
AlarmListeners class AlarmClock
{
l)
//...
void notifyListeners(AlarmEvent e) {
for each AlarmListener l in collection:
l.alarmActivated(e);
}
//..
}
alarmActivated()
addAlarmListener
(AlarmListener l)
instance of
AlarmClock
Alarm EventremoveAlarmListener
collection of
(AlarmListener
AlarmListeners class AlarmClock
{
l)
//...
void notifyListeners(AlarmEvent e) {
for each AlarmListener l in collection:
l.alarmActivated(e);
}
//..
}
alarmActivated()
instance of
AlarmClock
collection of
AlarmListeners
addAlarmListener
(AlarmListener l)
removeAlarmListener
(AlarmListener l)
Example: Alarm Clock
// A listener interface for receiving alarm events
// from a clock
public interface AlarmClockListener {
public void alarmActivated(AlarmEvent e);
}
// Encapsulator for information on the alarm event
public class AlarmEvent {
private AlarmClock eventSource;
private Clock alarmTime;
public AlarmEvent(AlarmClock source, Clock alarmTime)
{
//...
}
}
26
unit 15
Example: Alarm Clock
public class AlarmClock extends Clock {
private Clock alarmTime;
private Vector listeners;
public void secondElapsed() {
super.secondElapsed();
if (alarmTimeReached()) {
notifyListeners();
}
}
// returns true if alarm time has been reached
private boolean alarmTimeReached() {
return alarmTime.equals(this); // Clock comparison
}
27
unit 15
Adding and Removing Interested Listeners
// Adds the specified alarm listener to receive alarm
// events from this alarm clock.
// @param listener the alarm listener
public void
addAlarmClockListener(AlarmClockListener listener)
{
listeners.addElement(listener);
}
// Removes the specified alarm listener
public void
removeAlarmClockListener(AlarmClockListener listener)
{
listeners.removeElement(listener);
}
28
unit 15
Notifying Listeners
// Notifies all alarm listeners of an alarm event
private void notifyListeners() {
AlarmEvent event = new AlarmEvent(this, alarmTime);
for (int i = 0; i < listeners.size(); i++) {
AlarmClockListener listener =
(AlarmClockListener)listeners.elementAt(i);
listener.alarmActivated(event);
}
}
}
29
unit 15
Example: Alarm Clock Listener
public class InterestedListenerA implements
AlarmClockListener {
// instance variables...
public InterestedListenerA(…) {
// ...
}
public void alarmActivated(AlarmEvent event) {
System.out.println(“Wake me up before you go go”);
}
}
30
unit 15
Using AlarmClock
public class test {
public static void main(String[] args) {
InterestedListenerA IL = new InterestedListenerA();
AlarmClock alarmTime = new AlarmClock(0,0,1);
alarmTime.addAlarmClockListener(IL);
System.out.print("+1 second is passing: ");
alarmTime.secondElapsed();
System.out.print("+1 second is passing:");
alarmTime.secondElapsed();
}
}
31
unit 15
class Observable
inteface XXXListener
public
addXXXListener
(XXXListener l)
public
removeXXXListener
(XXXListener l)
private
notifyObservers()
public XXXHappened
(XXXEvent e)
...
collection of
XXXListeners
class Observer
implements XXXListener
public XXXHappened
(XXXEvent e)
...
Example: GUI components
A
Button
Remember to notify:
Please let me
know when you
are pressed
addActionListener()
actionPerformed()
Please let me
know when you
are pressed
removeActionListener()
B
When pressed.
OK
actionPerformed()
Button example: listening interface




A Button component fires an ActionEvent when it
is pressed
Components that are interested in reacting to these
events should ask the button to be notified of these
events
In order to be notified of these events an object
should implement the interface ActionListener
The interface ActionListener defines a method
called actionPerformed(); this method will be
used for notifying the object about the event
34
unit 15
Button example: listeners




If an object A wants to be notified about events of
pressing the Button, it should ask the button to
register it for receiving these events
It does so by calling the addActionListener()
method from the Button, passing a reference to
itself as a parameter
The Button keeps a list of references of type
ActionListener, to objects that wish to listen to it
When its addActionListener() method its called,
it adds the reference to the ActionListener that was
passed to the list of listeners
35
unit 15
Button example: listeners

Similarly, an object can remove itself from
listening to the Button by calling its
removeActionListener() method

When the button is pressed, it creates a new
ActionEvent object that encapsulates the
information about the press; it then goes over the
list of its listeners, and calls the method
actionPermored() for each of its listeners with
the new event as an argument
36
unit 15
GUI with AWT & Swing

Originally Java came with the very basic AWT
(Abstract Window Toolkit)

Swing is a much richer API for GUI, which
inherits many of the AWT features
37
unit 15
Some AWT components
Button:
Frame:
TextField:
Label:
Scrollbar:
Choice:
38
unit 15
The component class
All components are derived from the class java.awt.Component
Component
Button
TextComponent
TextArea
...
TextField
39
unit 15
The Component Class

Class component defines the properties common
to all GUI components: location, size, background
color, foreground color, visibility, ...
public
public
public
public
public
public
public
public
...
Dimension getSize()
void setSize(Dimension d)
void setSize(int x, int y)
Point getLocation()
void setLocation(Point p)
void setLocation(int x, int y)
Color getBackground()
void setBackground(Color c)
40
unit 15
The Container Class


Container is a subclass of Component that is a
superclass of all Components that can contain
other components
It adds to Component the functionality of
adding/removing components
public
public
public
public
...
void add(Component c)
void remove(Component c)
Component[] getComponents()
int getComponentCount()
41
unit 15
Frame: Window Container

A frame is a container that is free standing and can
be positioned anywhere on the screen

Frames give us the ability to do graphics and GUIs
through applications

Because a frame is a free standing window, it must
address window events
42
unit 15
Example: Opening a Frame
import java.awt.*;
// A sample program that opens a yellow frame
class FrameExample {
public static void main(String[] args) {
Frame frame = new Frame(“Example”);
frame.setSize(1000,600);
frame.setBackground(Color.yellow);
frame.setVisible(true);
}
}
43
unit 15
Opening a Frame: version II
A better code would be to define a new type of Frame with the
required properties:
// A sample program that opens a yellow frame
class FrameExample extends Frame {
public FrameExample () {
super(“Example”);
setSize(1000,600);
setBackground(Color.yellow);
}
public static void main(String[] args) {
new FrameExample().setVisible(true);
}
}
44
unit 15
GUI Components

There are various AWT/Swing GUI components that we
can incorporate into our window container:
•
•
•
•
•
•
•
labels (including images)
text fields and text areas
buttons
check boxes
radio buttons
menus
and many more…
45
unit 15
Buttons

GUI buttons fall into various categories:
• push button – a generic button that initiates some action
• check box – a button that can be toggled on or off
• radio buttons – a set of buttons that provide a set of mutually
exclusive options

Radio buttons must work as a group - only one can be
toggled on at a time; radio buttons are grouped using the
ButtonGroup class

Push buttons and radio buttons generate action events
when pushed or toggled; Check boxes generate item state
changed events when toggled
46
unit 15
Example: Adding Button Component
// A sample program that opens a frame with a button
class FrameExample extends Frame {
public static void main(String[] args) {
new FrameExample().setVisible(true);
}
public FrameExample () {
super(“Example”);
setSize(1000,600);
Button okButton = new Button(“OK”);
okButton.setSize(80,20);
okButton.setLocation(160,200);
add(okButton);
}
}
47
unit 15
Problem: Layout

When the window is resized, the button’s position and
size remains fixed

We would like an automatic and flexible mechanism
for repositioning components in a container, and
resizing them if needed
48
unit 15
Where and how are the components added?

There are two ways to layout components on a
container:
• Set the exact size and location of every component
• Use a LayoutManager

Every container has its own LayoutManager object,
which is responsible for the the layout of the
components inside the container

The LayoutManager is consulted whenever there is a
need to rearrange the components inside the container
(container size changed, component added... )
49
unit 15
Example: Layout Manager
add(new Button(“Ok”))
Frame
layoutContainer(this)
FlowLayout
50
unit 15
Layout Managers

There are various types of Layout Managers, each
having its own strategy for arranging components

Layout managers given with java.awt:
FlowLayout, BorderLayout, GridLayout,
CardLayout, GridBagLayout

You can define your own layout managers by
implementing the interface
java.awt.LayoutManager
51
unit 15
Flow Layout

A flow layout puts as many components on a row as
possible, then moves to the next row

Rows are created as needed to accommodate all of the
components

Components are displayed in the order they are added to
the container

The horizontal and vertical gaps between the components
can be explicitly set
52
unit 15
FlowLayout
setLayout(new FlowLayout());
add(new Label(“Name:”));
add(new TextField(10));
add(new Button(“Ok”));
53
unit 15
Border Layout

A border layout defines five areas into which
components can be added
North
West
Center
East
South
54
unit 15
BorderLayout
setLayout(new BorderLayout());
add(new Button(“North”), BorderLayout.NORTH);
add(new Button(“East”), BorderLayout.EAST);
add(new Button(“South”), BorderLayout.SOUTH);
add(new Button(“West”), BorderLayout.WEST);
add(new Button(“Center”), BorderLayout.CENTER);
55
unit 15
GridLayout
setLayout(new GridLayout(2,2));
add(new Button(“A”));
add(new Button(“B”));
add(new Button(“C”));
add(new Button(“D”));
56
unit 15
Combination of layouts
Frame with
BorderLayout
Panel with
GridLayout
setLayout(new BorderLayout());
TextField display = new TextField();
add(display, BorderLayout.NORTH);
Panel buttonsPanel = new Panel();
buttonsPanel.setLayout(new GridLayout(4,4));
String[] labels = {“7”,”8”,”9”,”+”,”4”,”5”, ... };
for (int i=0; i<labels.length; i++) {
buttonsPanel.add(new Button(labels[i]));
}
add(buttonsPanel,BorderLayout.CENTER);
Graphics

Every component can serve as a graphical context;
in order to draw on a component, you override its
paint method to define the drawing

You don’t call the paint method, it is called
automatically by the windowing system whenever
there is a need to display the component

paint() receives as parameter a Graphics object
which has methods for drawing on the component;
the widowing system provides the parameter
58
unit 15
Example: using Graphics
import java.awt.*;
// A frame that displays some graphics on it
class GraphicsExample extends Frame {
public void paint(Graphics painter) {
painter.setColor(Color.black);
painter.drawLine(20,20,400,300);
painter.setColor(Color.blue);
painter.drawRect(50,50,150,100);
painter.setColor(Color.yellow);
painter.fillOval(250,100,80,80);
painter.setColor(Color.green);
painter.fillRect(100,200,150,100);
}
}
59
unit 15
Graphics: repaint()

In order to display a dynamic drawing, the implementation
of paint should depend on the state of the object

Whenever the state changes, we need to call the repaint()
method in order to refresh the display of the component

repaint() asks the windowing system to call the paint()
method with the suitable graphics object

Actually, the windowing system calls the method update()
which clears the display and then calls the method paint()
60
unit 15
AWT event handling

We handle events fired by AWT components by
registering listeners to the events they fire

The various events fired by AWT components and
the interfaces of the corresponding listeners are
defined in the package java.awt.event
61
unit 15
AWT events and listeners
ActionEvent
TextEvent
MouseEvent
...
ActionListener
actionPerformed(ActionEvent)
TextListener
textValueChanged(TextEvent)
MouseListener
mouseClicked(MouseEvent)
mouseEntered(MouseEvent)
mouseExited(MouseEvent)
mousePressed(MouseEvent)
mouseReleased(MouseEvent)
MouseMotionListener
mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
...
62
unit 15
Example: ActionEvent listener
import java.awt.*;
import java.awt.event.*;
// A simple ActionListener that prints “clicked”
// whenever it is notified of an ActionEvent
class SimpleListener implements ActionListener {
// Called to notify this object that some
// action occured
public void actionPerformed(ActionEvent event)
{
System.out.println(“clicked”);
}
}
63
unit 15
Example: listening to button press
// An example of listening to the press of a button
class ListeningExample extends Frame {
public ListeningExample() {
Button okButton = new Button(“OK”);
add(okButton);
ActionListener listener = new SimpleListener();
okButton.addActionListener(listener);
}
public static void main(String[] args) {
new ListeningExample().setVisible(true);
}
}
64
unit 15
Example: Drawing Panel
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
// A panel that lets the user draw freehand lines
public class DrawingPanel extends Panel {
// The points composing the path drawn by the user
Vector path;
public DrawingPanel() {
addMouseListener(new StartDrawingAdapter(this));
addMouseMotionListener(new DrawingAdapter(this));
}
65
unit 15
Example: Drawing Panel
// Paints this component
public void paint(Graphics g) {
if (path==null) {
return;
}
for (int i=0; i<path.size()-1; i++) {
Point p1 = (Point)path.elementAt(i);
Point p2 = (Point)path.elementAt(i+1);
g.drawLine(p1.x, p1.y, p2.x, p2.y);
}
}
}
add to Frame object using: add(new DrawingPanel());
66
unit 15
Drawing panel: handling events
// Cleans the path at the beginning of the dragging
class StartDrawingAdapter implements MouseListener {
private DrawingPanel target;
public StartDrawingAdapter(DrawingPanel target) {
this.target = target;
}
public void mousePressed(MouseEvent e) {
target.path = new Vector();
}
public void mouseReleased(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
...
}
67
unit 15
Drawing panel: handling events
// Adds the points to the path during the dragging
class DrawingAdapter implements MouseMotionListener {
private DrawingPanel target;
public DrawingAdapter(DrawingPanel target) {
this.target = target;
}
public void mouseDragged(MouseEvent e) {
target.path.addElement(e.getPoint());
target.repaint();
}
public void mouseMoved(MouseEvent e) {
}
}
68
unit 15
Adapters

In the previous example we used adapter classes
which needed to implement all the methods
defined in the interface, sometimes empty

To avoid this effort, the API includes - for every
listener interface that defines more than a single
method - an adapter class that implements the
interface in a trivial way
69
unit 15
Adapters
package java.awt.event;
// Adapter for MouseEvents ...
public abstract class MouseAdapter implements
MouseListener{
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
// ... mouseExited, mouseClicked as well
}
70
unit 15
Handling events with Adapters
// Cleans the path at the beginning of the dragging
class StartDrawingAdapter extends MouseAdapter {
private DrawingPanel target;
public StartDrawingAdapter(DrawingPanel target)
{
this.target = target;
}
public void mousePressed(MouseEvent e) {
target.path = new Vector();
}
}
71
unit 15
Inner classes

In the previous examples the main class created
adapters to listen to and act upon itself

This adds to the complexity of the code:
• the main object has to pass a reference of itself to
the listener/adapter
• each listener/adapter has to define a field and a
suitable constructor to record the target object
• in each listener/adapter we make frequent use of
the target reference
72
unit 15
Inner classes

To make the code more compact (and less error
prone) we may use an inner class - class defined
inside the body of another class

An Instance of an inner-class has automatic access
to fields defined in the enclosing class, with no
need to denote the reference to the enclosing
object
73
unit 15
Inner classes
import java.awt.*;
import java.awt.event.*;
import java.awt.Vector;
// A panel that lets the user draw freehand lines
public class DrawingPanel extends Panel {
// The points composing the path drawn by the user
Vector path;
public DrawingPanel() {
addMouseListener(new StartDrawingAdapter());
addMouseMotionListener(new DrawingAdapter());
}
74
unit 15
Inner classes
// Paints this component
public void paint(Graphics g) {
if (path==null) {
return;
}
for (int i=0; i<path.size()-1; i++) {
Point p1 = (Point)path.elementAt(i);
Point p2 = (Point)path.elementAt(i+1);
g.drawLine(p1.x, p1.y, p2.x, p2.y);
}
}
75
unit 15
Inner classes
// Cleans the path at the beginning of the dragging
class StartDrawingAdapter extends MouseAdapter {
public void mousePressed(MouseEvent e) {
path = new Vector();
}
}
// Adds the points to the path during the dragging
class DrawingAdapter extends MouseMotionAdapter {
public void mouseDragged(MouseEvent e) {
path.addElement(e.getPoint());
repaint();
}
}
}
76
unit 15
Anonymous classes

If an inner class is needed only for a single use
and its constructor gets no parameters
we can define it as an anonymous class

Anonymous classes are defined in the place in the
code were they are needed, and an instance of the
anonymous class is immediately created

Anonymous classes should be used with care only when the code of the class is very short
77
unit 15
Anonymous classes
// .. as before
public class DrawingPanel extends Panel {
Vector path;
public DrawingPanel() {
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
path = new Vector();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
path.addElement(e.getPoint());
repaint();
}
});
}
78
public void paint // .. as before
unit 15