(GUI) Programming II

Download Report

Transcript (GUI) Programming II

Graphical User Interface (GUI)
Programming II
Lecture Objectives
• Understand the Event-Handling Processes in Java
Caution Note!!!
This lecture presentation contains a number of
"hidden" slides. Feel free to read, study and learn
from them on your own!!!
Outline for Today's Fun
• Events:
 What is an event?
 Simple (?) Example
• Swing Components:




JFrames
JComponents
An example
Swing Component Design (MVC/UI-Delegate??)
Events
• Behind the scenes, the Java runtime environment
is monitoring many things
• When any of a number of things happen an event
is said to occur. Sometimes the terminology is “an
event gets fired“
• Examples of the types of things that can "fire"
events:




Pressing a key on the keyboard
Clicking on a component (like a button)
Entering a component with the mouse pointer
Have a timer "time-out"
Events (Cont’d)
• Moving the mouse around any reasonably
complicated GUI can literally cause hundreds if
not thousands of events to occur.
• Events will be ignored except for the ones that
you tell Java that you are interested in doing
something about.
• Java maintains a data structure of all the events
that you have decided to handle and looks up
events and does what you tell it to do.
Code from the Past: Remember???
import java.awt.*;
public class HelloGUI {
public static void main (String[ ] args) {
System.out.println("About to make GUI");
Frame f = new Frame ("Hello GUIs");
f.setSize( 200, 200 );
f.show();
System.out.println("Finished making GUI");
}// main
}// class HelloGUI
Code from the Past: Remember???
What didn't work???
Making It Work (MIT Approach)!
• Determine which event occurs when the "Close
the Window" button is pressed:
 The API is your friend
 The lecture notes are your friend
 Hint: In this case it's an event called "Window Closing"
• You decide what class is going to handle this
event
 It might be the actual class which has the window.
 It can be any other class.
Making It Work (MIT Approach)!
• Write the method (and class?) that will handle the
event:
When this event occurs, Java is going to go to the
class that you identify as the event handler or
Listener. It will look for a method called:
public void windowClosing(WindowEvent e)
• Java will report an error to you if this class doesn't
have this method. How might the designers of
Java be guaranteed that you will implement this
method?
Interfaces: Back to School!
// Note: found in java.awt.event
public interface WindowListener extends EventListener {
void windowActivated(WindowEvent e);
void windowClosed(WindowEvent e);
void windowClosing(WindowEvent e);
void windowDeactivated(WindowEvent e);
void windowDeiconified(WindowEvent e);
void windowIconified(WindowEvent e);
void windowOpened(WindowEvent e);
}
Using Event Interfaces
Outline:
So we could write a class as shown below:
import java.awt.*;
Import
import java.awt.event.*;
public class Handler implements WindowListener {
public void windowActivated(WindowEvent e) {}
Class definition
public void windowClosed(WindowEvent e) {}
public void windowClosing(WindowEvent e) {
Window w = e.getWindow();
Implementation
w.setVisible(false);
w.dispose();
System.exit(0);
}
public void windowDeactivated(WindowEvent e)
Dummy (lazy)
implementation
{}
public void windowDeiconified(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
}
Using Event Interfaces (Cont’d)
• Register the listener with Java. That is, tell Java
in which class the method will be located to run
when the Window Closing Event occurs.
Event Handler Registration
import java.awt.*;
public class HelloGUI {
public static void main (String[] args) {
Handler h = new Handler();
System.out.println ("About to make GUI");
Frame f = new Frame ("Hello GUIs");
f.setSize( 200, 200 );
f.addWindowListener(h);
f.show();
System.out.println("Finished making GUI");
} // main
} // class HelloGUI
Demonstration
Class Pool
class HelloGUI
main {
Frame f
Handler h
}
class Frame
class Handler
Interface WindowListener
Frame
Instance
Handler
Instance
Event Handling: Key Ideas
1. Determine which event occurs
2. Decide what class is going to handle this event
3. Write the method (and class?) that will handle
the event.
4. Register the listener with Java.
Today’s First Wisdom
Very important that you
understand this simple example to
understand the concepts that
follow.
Potential Points of Confusion
• What exactly is the listener? Is it the component
getting clicked on?
 No, the listener is the object that contains the method
that Java will call when the event happens.
 You must tell the component getting clicked which object
that is by registering: addWindowListener...
 As we will see it could be the same!!!
• What type of listener do I use?




There are only so many.
See the Java API.
Lecture/Instructor/Lab/WebCT/Classmates/Friends.
Try yourself and experience the excitement!
Potential Points of Confusion (Cont’d)
• What about all those other window things (e.g.
windowActivated)
 We actually did implement them (with empty bodies) –
Lazy or dummy implementation!
 We said: Don't do anything!
Outline for Today's Fun: Reminder
• Events:
 What is an event?
 Simple (?) Example
• Swing Components:




JFrames
JComponents
An example
Swing Component Design (MVC/UI-Delegate)
A Call from the Past!
Earlier, we cautioned about
the existence of two toolkits
in Java for creating GUIs:
Java’s GUI Capabilities
Java provides essentially two related toolkits for
making GUIs:
1. The Abstract Windowing Toolkit (“AWT”), and
AWT
Swing
2. The Java Foundation Classes (“Swing”)
Swing is merely a new, improved version of the AWT,
and still uses some of AWT’s features.
Today, we examine a few Swing components.
The goal is to learn how Swing components in general are
designed, so that you can make better use of the API.
Swing: Sun’s Response to Microsoft?
• In 1997, Sun announced a new graphical toolkit for Java
called the “Java Foundation Classes”, or “JFC”.
• This is usually called “Swing”.
• The JFC/Swing classes provide well designed, powerful
widgets for GUI developers.
• Let’s take a look . . .
Welcome to JFC/Swing Planet
“Now it gets interesting . . . “
Historical Problems with AWT
•
All



•
Limited AWT widget library
 Addressed somewhat by JDK 1.1b3+, which allowed subclassing of components,
or “lightweights” (not covered in this course)
AWT components required runtime peer resources:
Slow on some platforms (notably Windows)
Portability problems (slightly different look, some behaviors different)
Least common denominator phenomenon: If one OS (e.g., Windows) did not
support a widget, the entire AWT had to suffer without it.
java.awt.Button
ButtonPeer
AWT components required
native “peer” methods to
render and operate--many steps!
WinNT
ButtonPeer
MacOS
ButtonPeer
Motif
ButtonPeer
File Edit
Help
CLICK ME
Slow & Inflexible!
Fixing AWT Problems
•
Developers avoided a few AWT limitations through:
 Pervasive use of lightweights (again, not covered in cs1312).
 e.g., tooltip simulation through threads/windows/components
 extensive coding around rigid look
 use of layered gifs
Bottom line: Making stuff look cool
or satisfying a client’s request
could be a nightmare!
File Edit
(Tooltips required
threads,
window
subclasses &
extensive
event handling)
Help
CLICK ME
Tooltip
(Layering of
components
requires layout
subclasses)
(Menu bars limited;
no images possible
without *extensive*
simulation through
components)
(Image buttons required
component subclassing,
methods to handle ‘click’
look, as well as event
handlers)
Introducing Swing/JFC
•
Sun addressed these problems by producing Java Foundation
Classes (JFC) i.e., Swing
•
Key elements:
 No reliance on native peers; the JVM does the work, and is faster
 Swing completely controls look and feel of all components:
• PLAF, or “pluggable look and feel”
 Superior design: MVC-esque (Model View Control)
File Edit
Help
CLICK ME
Fast, flexible, extensible!
javax.swing.JButton
Swing Packages
• All the new Swing components and classes need a home.
Where? A subject of great debate!
• For JDK 1.1, Sun used “com.sun.java.swing”; developers
revolted.
• Problem: developers complained this “com” designation was
not appropriate for “core” class--something part of language.
Why “javax”?
Solution:
* logical grouping
javax.swing.*
* minimizes transition
costs
* most developers
happy with it
Denotes ‘extension’ package that
has migrated to core status
* helps maintain
existing JDK 1.1 code
(cf. MFC lib breaks)
Overview of JFC/Swing Packages
•
javax.swing.plaf
• javax.swing
•
javax.swing.plaf.basic
• javax.swing.table
•
javax.swing.plaf.metal
• javax.swing.tree
•
javax.swing.plaf.multi
• javax.swing.border
• javax.swing.colorchooser
• javax.swing.filechooser
•
javax.swing.text
•
javax.swing.text.html
•
javax.swing.text.html.parser
•
javax.swing.text.rtf
• javax.swing.event
• javax.swing.undo
Overview of the Overview
Packages to
control the
“look and feel”
of Swing
Text-based widgets
(including html/rtf display)
Components,
including
“aggregate”
or complex
components
New event packages
Short Examples
1.
Widget Example: JButtons
•
The java.swing.JButton class implements a “state version” of a
java.swing.AbstractButton. Many methods come from the abstract
class:
 A variety of constructors (Strings, Icons, etc.);
 setRolloverEnabled(boolean);
 setIcon(Icon);
 setRolloverIcon(Icon);
 setActionCommand(String); -- an extra String tacked onto the event that
gets fired!
 setContentAreaFilled(boolean) -- transparency for icons!
 setModel(ButtonModel); -- sets the ‘type’ of Button (you can define your
own Button behaviors!)
 setMnemonic(char/int); -- set mnemonics for button
Lesson: Check the API
for useful behaviors.
Cool Buttons
import javax.swing.*;
public class HelloWorld2 extends JFrame {
Images from disk:
public JButton bNew;
public JPanel p;
public HelloWorld2() {
bNew = new JButton("New Document", new
ImageIcon("Document.gif"));
bNew.setRolloverEnabled(true);
bNew.setRolloverIcon(new ImageIcon("New.gif"));
p = new JPanel();
p.add(bNew);
getContentPane().add(p);
this.pack();
}
public static void main(String arg[ ]) {
new HelloWorld2().show();
}// class HelloWorld2
}
Sets icon and
rollover Icon.
Note: Icon constructor
took String argument,
and automatically
loaded image
Why getContentPane() ?
•
The HelloWorld example required us to call getContentPane() before
“add()”ing an object to the JFrame:
myFrameInstance.getContentPane().add(myComponent);
Usually
“this”
Required of
JFrame, JDialog
and JInternalFrame
instances
E.g.,
“myJButton”
• This differs from traditional AWT container additions, where we simply call “add”,
passing in the component.
• Let’s cut a JFrame open to find out why . . .
A JFrame Autopsy
“The Pop Tart / Sandwich Duality”
JLayeredPane
Menu
ContentPane
A java.awt.Frame is
composed of a single
container--the Frame object
itself. It is flat as a pop tart.
JPanel
A javax.swing.JFrame is
composed of a transparent
“glassPane” surface, and an
inner JPanel with Contents
and Menu
JFrame Class View
AWT
Component
GlassPane
Frame
Container
ContentPane
JComponent
contains
JFC
JRootPane
manages
JMenuBar
JFrame
The JRootPane is a container with a
JLayeredPane (holding the Menu
and ContentPane) and a Component
GlassPane. It serves as base for
numerous classes.
JLayeredPane
JRootPane: The Content Pane
The JRootPane contains only two components:
the JLayeredPane and
the Component GlassPane
Its layout manager ignores all attempts to add new components.
Instead, one must add to the JRootPane’s ContentPane, found inside the
JLayeredPane.
A call to getContentPane() returns an instance of the ContentPane.
JRootPane: The Glass Pane
public Component getGlassPane();
public void setGlassPane(Component);
JFrame Blue Print
We can use the top “glassPane”
as a drawing area. Since it spans the
entire JFrame, we can draw on top of
menu bars, and every component.
The JPanel has a remarkable
layering feature, allowing us to stack
and shuffle components.
public JPanel getContentPane();
JFrame Disposal
•
JFrame allows you to configure how it responds to closure.
 Default: hides JFrame on closure attempt.
 To modify: invoke setDefaultCloseOperation().
 E.g.,:
MyJFrameInstance.setDefaultCloseOperation(WindowConstants.DO_NOTHING_
ON_CLOSE);
/* behaves just like java.awt.Frame */
 other constants in javax.swing.WindowConstants:
 HIDE_ON_CLOSE - invokes any registered WindowListener object, then hides.
This is default behavior.
 DISPOSE_ON_CLOSE - invokes any registered WindowListener object, and
then disposes.
JComponent: The Generic Widget
• The JComponent provides the basis for all Swing
components.
• JComponent extends java.awt.Container, making all
Swing components large, powerful widgets.
(Also, all Swing components are also containers--even if
you wouldn’t normally place things in them. E.g.,
JButton)
• In turn, JComponent is subclassed by numerous widgets.
Thus, composition is favored over inheritance for widget
manipulation.
Jcomponent (Cont’d)
Since JComponent is the basis for most Swing components, all Swing
widgets have the following general features:
Borders
-- JComponent derived classes can have borders
Accessibility
-- JComponents use Swing’s accessibility features to provide
additional information about the widget.
Tooltips
-- JComponents can have time sensitive tooltips.
Double Buffering
-- By default, Swing components have double buffering built in
Serialization
-- Ability to save state to a file.
Events
Here, we review event handling one more time.
To understand how events work in Java, we have to look
closely at how we use GUIs.
When you interact with a GUI, there are many events
taking place each second. Only a few of these,
however, may actually be ‘delivered’ to the application.
Events (Cont’d)
Java uses a “delegation” event model found in many other
toolkits.
Under the delegation model, components fire events, which
can be caught and acted on by listeners. A listener is linked to
a component through a registration process.
The delegation event model is contrasted to an event filtration
model where all events are delivered to target components
regardless of whether they asked for them.
Events: General Overview
Recall our first
consideration of events,
where our first frame
would not close, even
when the end of main()
was reached.
We explained this behavior by thinking of our program as
entering an “infinite loop” when the graphics are shown. This
‘infinite loop’ is actually an event-driven cycle, but we can
think of it as a “while (true)” structure that periodically polls for
user input.
The Real Story
import java.awt.*;
public class HelloGUI {
public static void main (String[ ] arg) {
System.out.println
(“About to make GUI”);
Frame f = new Frame (“Hello GUIs”);
f.setSize( 200, 200 );
f.show();
System.out.println
(“Finished making GUI”);
}// main
}// class HelloGUI
We usually think of our program as a single, linear set of steps
being executed. But something special happens when we
create graphical objects.
The Real Story (Cont’d)
When Java sees that you’ve created a GUI, your program gets a second “set” of
linear instructions.
import java.awt.*;
public class HelloGUI {
public static void main (String[ ] arg) {
System.out.println
(“About to make GUI”);
Frame f = new Frame (“Hello GUIs”);
f.setSize( 200, 200 );
f.show();
System.out.println
(“Finished making GUI”);
}// main
}// class HelloGUI
This is actually a separate
“thread”, but don’t worry if
that’s unclear for now. We
can think of this as a
second part of our program
than handles special
graphics-related tasks
(such as drawing the
window, etc.)
The Real Story (Cont’d)
This model is very important to understand because as it turns
out, when an event occurs--such as mouse click, it happens in the
“graphics side” of the model.
import java.awt.*;
public class HelloGUI {
public static void main (String[ ] arg) {
System.out.println
(“About to make GUI”);
Frame f = new Frame (“Hello GUIs”);
f.setSize( 200, 200 );
f.show();
System.out.println
(“Finished making GUI”);
}// main
}// class HelloGUI
Mouse Click
occurs
The code trapping
this event appears
in the graphics thread
Actually, there’s a separate “event queue” that handles incoming events. But this is already
complicated enough. Let’s just generalize and imagine that all events arrive in the ‘graphics side’
of things.
The Real Story: “Call backs”
Since the event arrived in the ‘graphics half’ of our program,
we need a way to have it call a method in our program. This
is known as a “call back”.
Our event
handling
code
import java.awt.*;
public class HelloGUI {
public static void main (String[ ] arg) {
System.out.println
(“About to make GUI”);
Frame f = new Frame (“Hello GUIs”);
f.setSize( 200, 200 );
f.show();
System.out.println
(“Finished making GUI”);
}// main
}// class HelloGUI
callback
The code trapping
this event appears
in the graphics thread
The Real Story: How?
So Java needs to call some event handling code that we write.
The trouble is, how will Java know what we called out method?
We can name them anything we want, and Java won’t necessarily
know what methods handle events.
import java.awt.*;
public class HelloGUI {
public static void main (String[ ] arg) {
System.out.println
(“About to make GUI”);
Frame f = new Frame (“Hello GUIs”);
f.setSize( 200, 200 );
f.show();
System.out.println
(“Finished making GUI”);
}// main
}// class HelloGUI
callback
But Wait!
We can use
interfaces, right?
Event Interfaces
Java uses interfaces as its primary event handling scheme. If
you implement an event-related interface, Java will know which
methods to call. This is because the contract nature of
interfaces requires all methods to appear in the implementing
class.
ActionListener
import java.awt.*;
public class HelloGUI {
public static void main (String[ ] arg) {
System.out.println
(“About to make GUI”);
Frame f = new Frame (“Hello GUIs”);
f.setSize( 200, 200 );
f.show();
System.out.println
(“Finished making GUI”);
}// main
}// class HelloGUI
public void actionPerformed
(ActionEvent e) {
// code doing something
}
This method MUST
be there, so Java knows
it can “callback” to it
callback
Why “Registration”?
We are told that “event registration” must occur before event handling will
occur. What does this mean?
Well, since we can have any class handle events, we need to tell Java which
object implements the proper event handling interface.
This “registers” the component as being interested in receiving callbacks.
import java.awt.*;
public class HelloGUI {
public static void main (String[ ] arg) {
System.out.println
(“About to make GUI”);
Frame f = new Frame (“Hello GUIs”);
f.setSize( 200, 200 );
f.show();
System.out.println
(“Finished making GUI”);
}// main
}// class HelloGUI
Where to
callback?
An Example
public class DemoFrame extends Frame {
public DemoFrame( ) {
super (“A poor use of inheritance, but simple”);
Handler2 h = new Handler2();
this.setSize(400,400);
this.setLayout(new FlowLayout());
Button b = new Button (“Click me”);
this.add(b);
this.show();
} // Constructor
public static void main(String[] args) {
DemoFrame df;
df = new DemoFrame();
} // main
} // DemoFrame
Another Example
public class Handler2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println (“Button was clicked”);
}
} // Handler2
Why doesn’t this work?
Another Example (Cont’d)
public class DemoFrame extends JFrame {
public DemoFrame( ) {
super (“A poor use of inheritance, but simple”);
Handler2 h = new Handler2();
this.setSize(400,400);
this.setLayout(new FlowLayout());
JButton b = new JButton (“Click me”);
b.addActionListener(h);
add(b);
show();
} // Constructor
public static void main(String[] args) {
DemoFrame df;
df = new DemoFrame();
} // main
} // DemoFrame
Question???
We said we had to have a Listener to handle the
event and it had to be an object. Does it have to be
a separate object?
Another Example
public class DemoFrame extends Frame implements ActionListener {
public DemoFrame( ) {
super (“A poor use of inheritance, but simple”);
Handler2 h = new Handler2();
this.setSize(400,400);
this.setLayout(new FlowLayout());
Button b = new Button (“Click me”);
b.addActionListener(this);
this.add(b);
this.show();
} // Constructor
public void actionPerformed(ActionEvent e) {
System.out.println (“Button was clicked”);
}
public static void main(String[] args) {
DemoFrame df;
df = new DemoFrame();
} // main
} // DemoFrame
Is There Any Other Event There?
Anything can be an event. Including general protection faults.
But for the most part, good programming dictates that handled
events should come from the following area of input:
a
Mouse events
b
Keyboard events
c
Timing events
d
Other user action inputs
Java Event Handling Strategies
With this basic understanding, we can investigate the
FOUR primary means of event handling in Java
Very
similar
Very
general
Very
old
1
Event Listeners
2
Event Adapters
3
Semantic Events
4
Inheritance-based event handling
We’ll not talk about this one…
Listeners
From the discussion about callbacks, we noted
that interfaces were the primary mechanism for structuring
our event handling.
There are numerous event interfaces we can implement,
roughly divided around categories of events.
The next slide lists many of them. Don’t freak out because
there are so many.
We’ll highlight the most commonly used ones. . .
Listeners: So Many Choices
Package java.awt.event features:
ActionListener
Most commonly
used in this course
MouseListener
MouseMotionListener
AdjustmentListener
ComponentListener
FocusListener
ContainerListener
ItemListener
KeyListener
WindowListener
TextListener
As it turns out, the ActionListener is part of
the “semantic” event group, even though
it’s an interface. So let’s focus on simple
events like MouseListener...
MouseListener
The MouseListener interface has several methods we have to code:
public void mouseClicked(MouseEvent e) { }
-- a timing-based determination; else
the events are processed as
pressed/releases
public void mouseEntered(MouseEvent e) { }
-- entry into component
public void mouseExited(MouseEvent e) { }
-- exit from component
public void mousePressed(MouseEvent e)
-- simply a press . . .
{ }
public void mouseReleased(MouseEvent e){ }
-- ... the corresponding release
MouseListener: An Example
import java.awt.*;
import java.awt.event.*;
public class MouseFrame implements MouseListener{
Color highlight, normal;
boolean bHighlight = true;
Frame fr;
public MouseFrame () {
fr = new Frame(“For demonstration only”);
highlight = Color.red;
normal = Color.gray;
frame.setSize(400,400);
Button b = new Button("Click");
b.addMouseListener(this);
fr.setBackground(normal);
fr.setLayout(new FlowLayout());
fr.add(b);
fr.show();
}
public static void main(String[] args) {
new MouseFrame();
}
To keep it simple,
we ignore
WindowEvents
Note that when
we run this the
constructor will
run and terminate
MouseListener: An Example (Cont’d)
public void mouseReleased(MouseEvent e){
System.out.println ("Changing color");
if (bHighlight)
frame.setBackground(highlight);
else
frame.setBackground(normal);
bHighlight = !bHighlight;
}
public
public
public
public
void
void
void
void
mouseClicked(MouseEvent e) {}
mouseEntered(MouseEvent e) {}
mouseExited(MouseEvent e) {}
mousePressed(MouseEvent e) {}
} // MouseFrame
Event Listener Summary
We need a class that implements the appropriate listener
type.
We need to “register” a component as interested in
receiving events:
addXYZListener ( <listener instance> );
Whatever listener we’re working with. E.g.:
addMouseListener(this);
addMouseMotionListener(myEventHandler);
Event Listener: Observations
1
The “WindowListener” interface required numerous
methods.
2
But only one was important to us.
3
All the rest were coded as “no-op” or no operation methods.
There’s another strategy using “adapters”, using
inheritance that could have saved us some trouble...
Adapters
Java has built-in classes called “event
adapters” that implement each of the
various event listeners.
But all of these methods are “no-ops”.
public class MouseAdapter implements MouseListener {
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
}
WHY???
Key to Adapters: Inheritance
MouseAdapter
MouseFrame
Why a bunch of no-op methods?
Well, if you subclass the adapter, your class IS-A type of
event listener.
And you then only have to override the one or two
methods you care about. The rest can be inherited as “noops”
Event Adapters (Cont’d)
import java.awt.*;
import java.awt.event.*;
public class MouseFrame extends MouseAdapter
implements MouseListener{
Color highlight, normal;
boolean bHighlight = true;
Frame frame;
public MouseFrame () {
frame = new Frame(“For demonstration only”);
highlight = Color.red;
normal = Color.gray;
frame.setSize(400,400);
Button b = new Button("Click");
b.addMouseListener(this);
frame.setBackground(normal);
frame.setLayout(new FlowLayout());
frame.add(b);
frame.show();
}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
Parent
class
takes
care of
these
Event Adapters (Cont’d)
public void mouseReleased(MouseEvent e){
System.out.println ("Changing color");
if (bHighlight)
frame.setBackground(highlight);
else
frame.setBackground(normal);
bHighlight = !bHighlight;
}
We override
the one or
two methods
we care about
public static void main(String[] args) {
new MouseFrame();
}
} // MouseFrame
Same behavior; less code;
but we use up our
single inheritance
public class MouseAdapter implements MouseListener {
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
}
This comes with Java!
import java.awt.*;
import java.awt.event.*;
public class MouseFrame extends MouseAdapter implements MouseListener{
Color highlight, normal;
boolean bHighlight = true;
Frame frame;
public MouseFrame () {
frame = new Frame(“For demonstration only”);
highlight = Color.red;
normal = Color.gray;
frame.setSize(400,400);
Button b = new Button("Click");
b.addMouseListener(this);
frame.setBackground(normal);
frame.setLayout(new FlowLayout());
frame.add(b);
frame.show();
}
public void mouseReleased(MouseEvent e) {
System.out.println ("Changing color");
if (bHighlight)
frame.setBackground(highlight);
else
frame.setBackground(normal);
bHighlight = !bHighlight;
}
public static void main(String[] args) {
new MouseFrame();
}
} // MouseFrame
Big Picture Time
So far, we’ve tinkered with different ways of coding
very low-level event handling.
But what if our event handling needs are very general.
Consider this simple dialog box:
Are you sure you wish
to proceed ?
cancel
ok
There’s not much interaction
that needs to be supported.
Mouse entry/exit might not
be needed at all.
Event Handling Options: How to Decide?
Costs
Event Listeners
(interfaces)
Event Adapters
(inheritance)
Must code all
methods; wasteful
no-ops result
Uses up single
inheritance
opportunity
Benefits
Keep all
events in
single class
Good abstraction;
override those
methods
you need
Debugging Event Handlers
• Debugging an event-driven program (whether applet or graphical
application) is more tricky than debugging a non-event-driven
program.
• With an event-driven Java program, you don't explicitly code any
kind of event-handling loop that "polls" for occurring events, then
calls the appropriate handler(s) for those events.
• Instead, the Java internals handle this polling action for you.
Debugging becomes trickier because now you have to make sure
that your event handling code works correctly.
• You also have to make sure you're handling the correct events in
the first place! For example, your code for mouseEntered( ) may
work perfectly, but if you're expecting it to get called when the
user clicks a mouse button, it won't be!
Debugging Event Handlers (Cont’d)
So, in debugging event-driven programs written
with Java, the steps are:
• Be sure you're handling the appropriate events:
Map out on paper what events get thrown from what
components, and what class(es) handle them.
• Handle the events appropriately:
This is the kind of debugging you're already familiar with:
Once you're sure the appropriate events are getting
handled, the rest is being sure the event-handling
code (and the code that the event handlers call) work.
Events: A Short Example
To compare the three event handling techniques, let’s see a *brief*
example how all three might work on a common problem.
My Program
Goal: Create a
simple Frame that
holds a TextArea
and Button.
TEXT AREA
The Button toggles
the ability to edit
the TextArea
BUTTON
Panel subclass
The Panel
holding the
Button and
TextArea is
placed in a
Frame subclass,
which handles its
own disposal
Events: A Short Example (Cont’d)
import java.awt.*;
import java.awt.event.*;
public class MyFrame extends Frame implements WindowListener{
public static final int iWidth = 300, iHeight = 500;
public MyFrame() {
this.setSize(iWidth, iHeight);
this.addWindowListener(this);
Constructor
BorderLayout border = new BorderLayout();
this.setLayout(border);
}
public void windowClosing (WindowEvent e) {
e.getWindow().setVisible(false);
e.getWindow().dispose();
System.exit(0);
}
public void windowActivated(WindowEvent e) {}
WindowListener
public void windowClosed(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
Frames are not
public void windowIconified(WindowEvent e) {}
self-disposing!
public void windowOpened(WindowEvent e) {}
(Setting Frame
invisible first
}// class MyFrame
eliminate flicker.)
Events: A Short Example (Cont’d)
import java.awt.*;
Advanced feature:
import java.awt.event.*;
“Anonymous
public class MyFrame extends Frame {
public static final int
Inner Class”:
iWidth = 300,
used as a short
iHeight = 500;
cut. For your
public MyFrame()
code, use listeners
{
this.setSize(iWidth, iHeight);
this.addWindowListener
(new WindowAdapter()
{
Frames are not
public void windowClosing (WindowEvent e)
{
self-disposing!
e.getWindow().setVisible(false);
(Setting Frame
e.getWindow().dispose();
invisible first
System.exit(0);
eliminate flicker.)
}
});
BorderLayout border = new BorderLayout();
this.setLayout(border);
}
}// class MyFrame
Events: A Short Example (Cont’d)
import java.awt.*;
public class Driver
{
public static void main (String arg[]){
Notepad note = new Notepad();
MyFrame f = new MyFrame();
f.add(note, BorderLayout.CENTER);
f.show();
}//main
}//class Driver