Title: CS2
1CS2
- Module 35
- Category Elements of Java
- Topic GUI Events
- Objectives
- Events
- Interclass Communication
2CS 2
- Introduction to
- Object Oriented Programming
- Module 35
- Elements of Java
- GUI Events
3Nota Bene
- This lecture presentation contains a number of
"hidden" slides. Feel free to read, study and
learn from them on your own!
4Today's Plan for Fun
- Events
- What is an event?
- Simple (?) Example
- Swing Components
- JFrames
- JComponents
- An example
- Swing Component Design (MVC/UI-Delegate)
5Events
- 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"
6Events
- 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.
7Remember this???
- 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
8What didn't work???
9Making it work
- 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
- 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?
10An Interface!!!
- // 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)
-
11So we could write a class like this
- import java.awt.
- import java.awt.event.
- public class Handler implements WindowListener
-
- public void windowActivated(WindowEvent e)
- public void windowClosed(WindowEvent e)
- public void windowClosing(WindowEvent e)
-
- Window w e.getWindow()
- w.setVisible(false)
- w.dispose()
- System.exit(0)
-
- public void windowDeactivated(WindowEvent e)
- public void windowDeiconified(WindowEvent e)
- public void windowIconified(WindowEvent e)
- public void windowOpened(WindowEvent e)
12Making it work II
- 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.
13Registration
- import java.awt.
- public class HelloGUI
-
- public static void main (String arg)
- 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
14Demonstration
15Diagramatically
Class Pool
class HelloGUI main Frame f Handler
h
class Frame
class Handler
Interface WindowListener
Frame Instance
Handler Instance
16Key Ideas
- Determine which event occurs
- Decide what class is going to handle this event
- Write the method (and class?) that will handle
the event. - Register the listener with Java.
17Questions?
- Very important that you understand this simple
example to understand the concepts that follow.
18Potential 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 API
- Lecture/Instructor/Recitation/TA/etc.
- Experience!
- What about all those other window things (e.g.
windowActivated) - We actually did implement them (with empty
bodies) - We said Don't do anything!
19Questions?
20Today's Plan for Fun
- Events
- What is an event?
- Simple (?) Example
- Swing Components
- JFrames
- JComponents
- An example
- Swing Component Design (MVC/UI-Delegate)
21Recall
Earlier, we cautioned about the existence of two
toolkits in Java for creating GUIs AWT Swing
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.
22Swing?
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. Lets take a look .
. .
23JFC/Swing
- Now it gets interesting . . .
24Historical Problems with AWT
- All 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. - Limited AWT widget library
- addressed somewhat by JDK 1.1b3, which allowed
subclassing of components, or lightweights (not
covered in this course)
25Stop-gap remedies for JDK 1.1b3
- 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 clients request could be a nightmare!
26Introducing Swing/JFC
- Sun addressed these problems by producing Java
Foundation Classes (JFC) a.k.a. 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)
Fast, flexible, extensible!
27Swing 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. - Solution
-
Why javax? logical grouping minimizes
transition costs most developers happy with
it helps maintain existing JDK 1.1 code (cf.
MFC lib breaks)
javax.swing.
Denotes extension package that has migrated to
core status
28Overview of JFC/Swing Packages
- javax.swing
- javax.swing.table
- javax.swing.tree
- javax.swing.border
- javax.swing.colorchooser
- javax.swing.filechooser
- javax.swing.event
- javax.swing.undo
- javax.swing.plaf
- javax.swing.plaf.basic
- javax.swing.plaf.metal
- javax.swing.plaf.multi
- javax.swing.text
- javax.swing.text.html
- javax.swing.text.html.parser
- javax.swing.text.rtf
29Overview of the Overview
Components, including aggregate or
complex components
Packages to control the look and feel of Swing
Text-based widgets (including html/rtf display)
New event packages
30Getting into the Swing
- Download from www.javasoft.com
- Swing works with JDK 1.1 and JDK 1.2
- JDK 1.1 requires swingall.jar file in the
CLASSPATH - For JDK 1.2, its already included (no CLASSPATH
settings needed) - JDK 1.2 will also run all JDK 1.1 code ( 20
faster!) - Thus, even older JDKs can make use of Swing, with
a CLASSPATH setting.
import com.sun.java.swing.
import javax.swing.
AWT
JDK 1.1
classpath
swingall.jar
31Short Examples
1.
32Short Example Old AWT
import java.awt. public class HelloWorld
extends Frame public Button bOld
//public Panel p public HelloWorld()
bOld new Button ("Good Bye") //p new
Panel() //p.add(bOld) //this.add(p)
this.add(bOld) / note the addition
directly to the Frame / this.pack()
public static void main(String arg) /
note lack of listener this is a demo / new
HelloWorld().show() // class HelloWorld
We comment most of this out for now AWT lets us
add directly to the Frame.
33Hello Swing, Good Bye AWT
- import java.awt.
- import java.awt.event.
- import javax.swing.
- public class HelloWorld extends JFrame
- Button bOld public JButton bNew
- public JPanel p
- public HelloWorld()
- bNew new JButton("Hello")
- bOld new Button ("Good Bye")
- p new JPanel()
- p.add(bNew) p.add(bOld)
- this.getContentPane().add(p)
- this.pack()
-
- public static void main(String arg)
- new HelloWorld().show()
-
- // class HelloWorld
Note Swing components
Note addition of components to JPanels
content pane
SEE CAUTIONARY NOTE RE Mixing light and
heavyweight components!
34Whats the Big Deal?
- HelloWorld looks similar to AWT. Why switch to
JFrame, JButton, JPanel, etc? - Benefits
- speed
- lightweight flexibility (transparency,
non-rectangular shape) - pluggable look and feel
- automatic double buffering with many J-
components. - additional functionality (e.g., tooltips, etc.)
Im lightweight, pluggable, extensible and fast.
The VM draws me.
I need Windows to be visible and toggle. Im
slow.
35Widget 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.
36Cool Buttons
- import javax.swing.
- public class HelloWorld2 extends JFrame
- 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
37Demonstration
38Why getContentPane() ?
- The HelloWorld example required us to call
getContentPane() before add()ing an object to
the JFrame
myFrameInstance.getContentPane().add(myComponent)
Required of JFrame, JDialog and
JInternalFrame instances
Usually this
E.g., myJButton
- This differs from traditional AWT container
additions, where we simply call add, passing in
the component. - Lets cut a JFrame open to find out why . . .
39A JFrame Autopsy
The Pop Tart / Sandwich Duality
40JFrame Class View
Component
AWT
GlassPane
Frame
Container
contains
manages
ContentPane
JComponent
JFC
contains
JMenuBar
manages
JRootPane
JFrame
contains
contains
The JRootPane is a container with a JLayeredPane
(holding the Menu and ContentPane) and a
Component GlassPane. It serves as base for
numerous classes.
contains
JLayeredPane
41JRootPane 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 JRootPanes ContentPane, found
inside the JLayeredPane. A call to
getContentPane() returns an instance of the
ContentPane.
42JRootPane The Glass Pane
public Component getGlassPane() public void
setGlassPane(Component)
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()
43JFrame 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.
44Questions?
45Questions?
46JComponent 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 wouldnt 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.
47JComponent
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 Swings 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.
48Demo A GlassPane Example
import java.awt. import java.awt.event. import
javax.swing. public class GlassDemo extends
JFrame implements ActionListener private
boolean bGlassVisible private GlassPanel
glass private JButton button
This demo will not be covered in class it is
provided as an example of how to work with
JFrames.
Heres a simple example that shows how to use
aspects of JFrames. Frist, we make a JFrame
subclass. We declare some instance variables a
GlassPanel (described later), a boolean flag
for the glass panels visibility, and a JButton
to toggle
49Glass Panel Example
import java.awt. import java.awt.event. import
javax.swing. public class GlassDemo extends
JFrame implements ActionListener private
boolean bGlassVisible private GlassPanel
glass private JButton button public
void actionPerformed (ActionEvent
e) bGlassVisible !bGlassVisible glass.setVis
ible(bGlassVisible)
The actionPerformed method merely toggles the
visibility of the glass pane
50Glass Panel Example
import java.awt. import java.awt.event. import
javax.swing. public class GlassDemo extends
JFrame implements ActionListener private
boolean bGlassVisible private GlassPanel
glass private JButton button public
void actionPerformed (ActionEvent
e) bGlassVisible !bGlassVisible glass.setVis
ible(bGlassVisible) public void
centerInScreen() Toolkit tk
Toolkit.getDefaultToolkit() Dimension d
tk.getScreenSize() this.setLocation((d.width-get
Size().width)/2, (d.height-getSize().height)
/2)
... A little magic. (It merely centers the
frame in the screen.)
51Glass Panel Example
import java.awt. import java.awt.event. import
javax.swing. public class GlassDemo extends
JFrame implements ActionListener private
boolean bGlassVisible private GlassPanel
glass private JButton button public
void actionPerformed (ActionEvent
e) bGlassVisible !bGlassVisible glass.setVis
ible(bGlassVisible) public void
centerInScreen() Toolkit tk
Toolkit.getDefaultToolkit() Dimension d
tk.getScreenSize() this.setLocation((d.width-get
Size().width)/2, (d.height-getSize().height)
/2) public static void main(String
args) new GlassDemo().show()
A simple test main
52public GlassDemo () this.setSize(400,400) thi
s.getContentPane().setBackground(Color.white) th
is.getContentPane().setLayout(new
BorderLayout()) this.addWindowListener (new
WindowAdapter() public void windowClosing(Windo
wEvent e) System.exit(0) )
Our constructor has poor abstraction, but is
sufficient for a demonstration. We start by
setting a size, background, layout, and a simple
WindowListener
53public GlassDemo () this.setSize(400,400) thi
s.getContentPane().setBackground(Color.white) th
is.getContentPane().setLayout(new
BorderLayout()) this.addWindowListener (new
WindowAdapter() public void windowClosing(Windo
wEvent e) System.exit(0) ) JPanel p
new JPanel() p.setLayout(new BoxLayout(p,
BoxLayout.X_AXIS)) button new JButton
("Toggle") button.addActionListener(this) p.ad
d(Box.createHorizontalGlue()) p.add(button) p.
add(Box.createHorizontalGlue())
We add a JButton to a containing JPanel. We
make sure it will center in the JPanel, using
glue objects. The same effect can be obtained
with more complicated layerings of panels and
layout managers.
54public GlassDemo () this.setSize(400,400) thi
s.getContentPane().setBackground(Color.white) th
is.getContentPane().setLayout(new
BorderLayout()) this.addWindowListener (new
WindowAdapter() public void windowClosing(Windo
wEvent e) System.exit(0) ) JPanel p
new JPanel() p.setLayout(new BoxLayout(p,
BoxLayout.X_AXIS)) button new JButton
("Toggle") button.addActionListener(this) p.ad
d(Box.createHorizontalGlue()) p.add(button) p.
add(Box.createHorizontalGlue()) this.getContentP
ane().add(p, BorderLayout.CENTER) this.getConten
tPane() .add(new JLabel("Press Button to
Toggle Glass Pane"), BorderLayout.SOUTH)
We add the panel to our JFrames content
pane, along with a simple label. . .
55public GlassDemo () this.setSize(400,400) thi
s.getContentPane().setBackground(Color.white) th
is.getContentPane().setLayout(new
BorderLayout()) this.addWindowListener (new
WindowAdapter() public void windowClosing(Windo
wEvent e) System.exit(0) ) JPanel p
new JPanel() p.setLayout(new BoxLayout(p,
BoxLayout.X_AXIS)) button new JButton
("Toggle") button.addActionListener(this) p.ad
d(Box.createHorizontalGlue()) p.add(button) p.
add(Box.createHorizontalGlue()) this.getContentP
ane().add(p, BorderLayout.CENTER) this.getConten
tPane() .add(new JLabel("Press Button to
Toggle Glass Pane"), BorderLayout.SOUTH) cen
terInScreen() glass new GlassPanel() this.se
tGlassPane(glass) bGlassVisible false
// end of class GlassDemo
We then make and set a new glass panel for the
JFrame.
56import java.awt. import javax.swing. public
class GlassPanel extends JComponent final
Color trans public GlassPanel ()
this.setOpaque(false) // create nearly black
color with transparency trans new
Color(150,25,25,125) public Dimension
getPreferredSize() return getParent().getPreferr
edSize() public void
paintComponent(Graphics g) g.setColor(trans) g
.fillRect(0,0,getSize().width, getSize().height)
// GlassPanel
57import java.awt. import javax.swing. public
class GlassPanel extends JComponent final
Color trans public GlassPanel ()
this.setOpaque(false) // create nearly black
color with transparency trans new
Color(150,25,25,125)
Our GlassPanel object is merely a JComponent
subclass. It first sets itself to be
transparent, and then creates a color with a
high transparency value, 125. (A later lecture
will touch on the Java color model. For now,
the API shows us the arguments are Red, Blue,
Green, and Alpha transparency.)
58import java.awt. import javax.swing. public
class GlassPanel extends JComponent final
Color trans public GlassPanel ()
this.setOpaque(false) // create nearly black
color with transparency trans new
Color(150,25,25,125) public Dimension
getPreferredSize() return getParent().getPreferr
edSize()
Since were making our own home-grown widget,
and not one found in the API, we have to let the
layout managers know how large this
component wishes to be. We simply return the
size of the parent container--meaning the
GlassPanel have the same size as its parent
container.
59import java.awt. import javax.swing. public
class GlassPanel extends JComponent final
Color trans public GlassPanel ()
this.setOpaque(false) // create nearly black
color with transparency trans new
Color(150,25,25,125) public Dimension
getPreferredSize() return getParent().getPreferr
edSize() public void
paintComponent(Graphics g) g.setColor(trans) g
.fillRect(0,0,getSize().width, getSize().height)
// GlassPanel
This method defines how the component will look.
Another lecture will explore the details of
drawing in Java. For now, know that this floods
the component with colored pixels.
60Overview of GlassDemo
GlassDemo (A JFrame subclass )
GlassPanel class
content pane (with JButton)
61(Demo)
After a press, the glass pane becomes visible,
giving a hazy gauze to the GUI.
62Design
3.
63Button Design
- JButtons are a good example of the Model, View,
Control paradigm used by Java (borrowed and
modified from older language Smalltalk) - Lets examine the inheritance structure of a
JButton . . .
public interface javax.swing.ButtonModel extends
ItemSelectable
java.lang.Object --java.awt.Component
--java.awt.Container
--javax.swing.JComponent
--javax.swing.AbstractButton
--javax.swing.JButton
hasA
AbstractButton implements ItemSelectable,
SwingConstants Defines the common behaviors for
the JButton, JToggleButton, JCheckbox, and the
JRadioButton classes.
The ButtonModel provides the state machine for
Button behavior
64Model, View, Control
- Let's say you decide to write a program that will
implement a timer - You want to be able to
- set the time,
- start and
- stop the timer
- You want the timer to show the time counting down
plus have something exciting happen when time is
up. - You might write a big monolithic program that
would do all this and be swell... - Until someone wanted a version with a different
display...perhaps some LED's, perhaps a graphical
widget. - Or until someone wanted a version with a
different control scheme like JButtons
65MVC
- Design the timer in three distinct parts (e.g. 3
classes!) - Model This is the heart of the calculation part
of the timer and is where the data is stored.
The model might not know anything about the View
or the Control - View The view controls what the user sees (and
hears). It might run autonomously or be
controlled by the Control. It might have a
reference to the Control - Control This is what the user interacts with to
control the timer. It may be a set of keyboard
commands or a GUI or mechanical pushbuttons. The
control has references to model and the view.
66MVC Relationships
View Model m Control c
Model (data)
Controller Model m View v
Clear Interfaces
67MVC Paradigm
- The MVC paradigm breaks applications or
interfaces into three parts the model, the view,
and the controller.
Users interact with a controller (e.g., buttons),
and make changes to the model (e.g., data), which
is then reflected in the view (e.g., graph).
68MVC Paradigm, à la Swing
- Swing uses a simplified version of the MVC
structure, called the model-delegate
69MVC Who Cares?
?
Helps us understand complex Swing packages
Guides future package development
Why does it matter?
Allows user customization of model or view,
without rewriting both
(Think of something else need four points)
70MVC Why You Care
The formal benefits of MVC will be exposed in
subsequent CS classes focused on design and OO
theory. But you should be familiar with MVC now
because Swing widgets use the UI-Delegate
variation of MVC. If you need to change
something about a Swing widget, consider whether
your proposed change affects
The model of a widget (its state, value)
The look of a widget (its UI
delegate) Knowing what you are changing will
help you find where in the API you must look for
useful methods.
71Questions
72Danger
4.
73Cautionary Notes MVC Threads
- An artifact of the MVC (or model-delegate)
structure of Swing is the need to avoid separate
threads updating the model state - To avoid a race condition, one should ONLY use
the event-dispatching queue.
The event-dispatching queue handles repaints, and
dispatches events to GUI component listeners.
Confused by this? The lesson is Dont mix
Threads and Swing unless you know exactly what
youre doing.
74Cautionary Note Mixing Types
- Avoid mixing light and heavy weight components.
- Heavy weights are opaque -- solid rectangular
- Light weights are transparent, and draw
themselves on top of the heavyweight container
they occupy (Frame, Jframe, Panel, etc.) - This can frustrate Z-order layering
- (The slides will violate this principle only to
make a point.)
Lightweight java.awt.Component
Heavy weight java.awt.Button
What shows up
As designed, and as we coded it
75Possible Solution Use Timers
We normally think of events as user-driven
actions. But the mere passage of time is an
event that Swing components can observe--all
without the use of additional threads. Java
provides the javax.swing.Timer object--something
of an egg timer that allows one to have an
event fired periodically without user
interaction
delay
Event handler
Timer t new Timer(500, this) t.start()
76import javax.swing. import java.awt.event. imp
ort java.awt. public class StopWatch extends
JLabel implements ActionListener int count
0 public StopWatch()
super("Elapsed Time 0 secs", JLabel.CENTER)
Timer t new Timer(1000, this) t.start()
public void actionPerformed(ActionEvent
e) this.setText("Elapsed Time "
count " secs") public static void
main (String arg) JFrame f new JFrame()
f.setSize(300,100) f.addWindowListener (new
WindowAdapter() public void
windowClosing(WindowEvent e)
System.exit(0)) StopWatch c new
StopWatch() f.getContentPane()
.setLayout(new BorderLayout())
f.getContentPane() .add(c, BorderLayout.CENTER
) f.show()
77Questions?
78Events
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.
79Events
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.
80General 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.
81The Real Story
We usually think of our program as a
single, linear set of steps being executed. But
something special happens when we create
graphical objects.
82The Real Story
When Java sees that youve created a GUI, your
program gets a second set of linear
instructions.
This is actually a separate thread, but dont
worry if thats 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.)
83Graphics Thread
Both of these threads are your program. You
coded one of the lines of control. Java provides
the other one. That way, things appear to happen
simultaneously--your code executes and the window
gets redrawn, refreshed, etc.
Java quickly switches between your code and the
graphics drawing code, so that both threads
appear to execute at the same time.
84Dont Panic
Dont worry if this thread stuff is confusing.
Other classes go into this in detail. For our
purposes, we only have to understand that there
are two areas of a graphic program.
1
The code we wrote in main() and other methods
Your Code
Graphics
The code Java provides to handle the graphics
side of things.
2
85Who Cares?
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.
Mouse Click occurs
The code trapping this event appears in the
graphics thread
Actually, theres a separate event queue that
handles incoming events. But this is already
complicated enough. Lets just generalize and
imagine that all events arrive in the graphics
side of things.
86Call 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.
The code trapping this event appears in the
graphics thread
Our event handling code
callback
87How?
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 wont necessarily know
what methods handle events.
But Wait! We can use interfaces, right?
88Event 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.
public void actionPerformed
(ActionEvent e) // code doing something
This method MUST be there, so Java knows it can
callback to it
89Why Delegation?
Since any class can implement any interface, we
can have just about any object handle the events.
We can therefore delegate event handling to
this object.
Remember MVC? Some (smart) folks believe you
should organize where the events get
handled. (This is the controller aspect to
MVC.)
M
V
C
90Why 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.
Where to callback?
91Another 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
92Another example
- public class Handler2 implements ActionListener
- public void actionPerformed(ActionEvent e)
- System.out.println (Button was clicked)
-
- // Handler2
Why doesnt this work?
93Another 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)
- b.addActionListener(h)
- this.add(b)
- this.show()
- // Constructor
- public static void main(String args)
- DemoFrame df
- df new DemoFrame()
- // main
- // DemoFrame
94Question...
- 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?
95Another 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()
96Questions?
97BSOD
This program has performed an illegal
instruction and will be shutdown. Please shell
out another 200 for a more stable version of
this OS.
98Just Kidding
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
99Java Event Handling Strategies
With this basic understanding, we can investigate
the FOUR primary means of event handling in Java
Well not talk about this one
You are 100 guaranteed to have a quiz question
on this
100Listeners
Strategy No. 1
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. Dont freak out
because there are so many. Well highlight the
most commonly used ones. . .
101Yikes. So Many Choices
Package java.awt.event features
ActionListener MouseListener MouseMotionListener
AdjustmentListener ComponentListener FocusListene
r ContainerListener ItemListener KeyListener Windo
wListener TextListener
As it turns out, the ActionListener is part of
the semantic event group, even though its an
interface. So lets focus on simple events like
MouseListener...
102MouseListener
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(MouseEv
ent e) -- ... the corresponding release
103import java.awt. import java.awt.event. publi
c class MouseFrame implements MouseListener Colo
r highlight, normal boolean bHighlight
true Frame fr public MouseFrame () fr
new Frame(For demonstration only) highlight
Color.red normal Color.gray frame.setSiz
e(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
(more)
104 public void mouseReleased(MouseEvent
e) System.out.println ("Changing color") if
(bHighlight) frame.setBackground(highlight)
else frame.setBackground(normal) bHighlight
!bHighlight public void mouseClicked(MouseEv
ent e) public void mouseEntered(MouseEvent e)
public void mouseExited(MouseEvent e)
public void mousePressed(MouseEvent e)
// MouseFrame
click
click
105Event Listener Summary
We need a class that implements the appropriate
listener type. We need to register a component
as interested in receiving events
addXYZListener ( ltlistener instancegt )
Whatever listener were working with.
E.g. addMouseListener(this) addMouseMotionListe
ner(myEventHandler)
106Observations
The WindowListener interface required numerous
methods. But only one was important to us. All
the rest were coded as no-op or no operation
methods.
1
2
3
Theres another strategy using adapters, using
inheritance that could have saved us some
trouble...
107Adapters
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?
108Key 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 no-ops
109import 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) f
rame.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
110Example (contd)
public void mouseReleased(MouseEvent
e) System.out.println ("Changing color") if
(bHighlight) frame.setBackground(highlight)
else frame.setBackground(normal) bHighligh
t !bHighlight public static
void main(String args) new MouseFrame()
// MouseFrame
We override the one or two methods we care about
Same behavior less code but we use up our
single inheritance
111public 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.ad
dMouseListener(this) frame.setBackground(normal
) frame.setLayout(new FlowLayout()) frame.ad
d(b) frame.show() public void
mouseReleased(MouseEvent e) System.out.println
("Changing color") if (bHighlight) frame.se
tBackground(highlight) else frame.setBackgro
und(normal) bHighlight !bHighlight publi
c static void main(String args) new
MouseFrame() // MouseFrame
112Big Picture Time
So far, weve 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
Theres not much interaction that needs to be
supported. Mouse entry/exit might not be needed
at all.
Are you sure you wish to proceed ?
cancel
ok
113Semantic Events
Wouldnt it be convenient to abstract all of
these small events into one just-tell-me-when-its
-clicked event?
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)
M1A1 Abstractor
public void actionPerformed(ActionEvent e)
114Semantic Events
Strategy No. 3
Semantic events provide a means of
handling events at the component level. That is,
you will not address fine-grained events like
mouse entry and exit. Instead, youll only
receive a callback when the component has
received some type of input event
115Semantic Events
Semantic Event
Components and Firing Event
ActionEvent
Button (activated)
List (double-clicked)
There are numerous event handlers for low-level
events associated with these widgets.
MenuItem (selected)
TextField (typed)
AdjustmentEvent
Scrollbar (moved)
ItemEvent
Checkbox (toggled) CheckboxMenuItem
(selected) Choice (selected) List (selected)
TextEvent
TextComponent (text changes)
Note ALL input is sent into one of these FOUR
categories.
116Example
import java.awt. import java.awt.event. public
class MouseFrame extends Frame
implements ActionListener Color
highlight, normal boolean bHighlight
true public MouseFrame () highlight
Color.red normal Color.gray this.setSize(400
,400) Button b new Button("Click") b.addActi
onListener(this) this.setBackground(normal) th
is.setLayout(new FlowLayout()) this.add(b) thi
s.show()
117Example (contd)
public void actionPerformed(ActionEvent
e) System.out.println ("Changing color") if
(bHighlight) this.setBackground(highlight)
else this.setBackground(normal) bHighlight
!bHighlight public static void
main(String args) new MouseFrame()
// MouseFrame
We therefore lose the ability to handle very
fine-grained events (e.g., mouse entry/exit).
But that might be acceptable for certain
applications.
118(non) Option 4 JDK 1.02 Events
- An earlier version of Java used boolean return
values to indicate consumption of events.
Events were delivered to components whether or
not they registered for events. - Not recommended still used for some web
development - Do not mix JDK 1.1 and JDK 1.02 event
handlers--the component ceases to function! - Rare use JDK 1.02 guarantees which event will
arrive first to a component. - More common use some browsers only support JDK
1.02--a very early version of Java that uses this
model. Professional applet developers still use
this technique. Many browsers are now supporting
the JDK 1.1 event model.
119Event Handling Options How to Decide
Costs Benefits
Event Listeners (interfaces) Event
Adapters (inheritance) Semantic Events
Must code all methods wasteful no-ops result
Keep all events in single class
Uses up single inheritance opportunity
Good abstraction override those methods you need
Simplifies event handling
Loss of granular control linear code
120Debugging re 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!
121Debugging re Event Handlers
- 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.
System.out.println is still your friend...
122Events A Short Example
To compare the three event handling techniques,
lets see a brief example how all three might
work on a common problem.
Goal Create a simple Frame that holds a
TextArea and Button. The Button toggles the
ability to edit the TextArea
The Panel holding the Button and TextArea is
placed in a Frame subclass, which handles its own
disposal
TEXT AREA
BUTTON
Panel subclass
123import 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.addWindo
wListener(this) BorderLayout border new
BorderLayout() this.setLayout(border) publ
ic void windowClosing (WindowEvent e)
e.getWindow().setVisible(false) e.getWindow
().dispose() System.exit(0) public void
windowActivated(WindowEvent e) public void
windowClosed(WindowEvent e) public void
windowDeactivated(WindowEvent e) public void
windowDeiconified(WindowEvent e) public void
windowIconified(WindowEvent e) public void
windowOpened(WindowEvent e) // class MyFrame
Constructor
WindowListener
Frames are not self-disposing! (Setting Frame
invisible first eliminate flicker.)
124Advanced featureAnonymous Inner Class used
as a short cut. For your code, use listeners
import java.awt. import java.awt.event. public
class MyFrame extends Frame public static
final int iWidth 300, iHeight 500
public MyFrame() this.setSize(iWidth,
iHeight) this.addWindowListener (new
WindowAdapter() public void
windowClosing (WindowEvent e)
e.getWindow().setVisible(false) e.getWind
ow().dispose() System.exit(0)
) BorderLayout border new BorderLayout() th
is.setLayout(border) // class MyFrame
Frames are not self-disposing! (Setting Frame
invisible first eliminate flicker.)
125import 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
A simple driver. Notice that so far, weve
abstracted the Frame subclass into something
very generic and reusable--ITS NOT JUST TIED TO
THIS PROGRAM!
126Variation 1 Listener Events (MouseListener)
import java.awt. import java.awt.event. class
Notepad extends Panel implements MouseListener
Button toggle TextArea scratch
boolean bWritable public Notepad()
super("Wasted inheritance") this.setLayout
(new BorderLayout()) scratch new
TextArea(20,20) Panel buttonPanel new
Panel() toggle new Button ("Freeze/Unfreeze")
buttonPanel.add(toggle) add(scratch,
BorderLayout.CENTER) add(buttonPanel,
BorderLayout.SOUTH) toggle.addMouseListener(this
) bWritable false // constructor
The Driver and MyFrame classes were generic
enough to work with any version of this example.
Here, however, we need to create a specific
event handler.
127 / . . . Continued from class Notepad extends
Panel implements MouseListener . . .
/ public void setWritable(boolean
bWritable) this.bWritable bWritable
//setWritable public boolean getWritable()
return bWritable //getWritable
public TextArea getTextArea() return
scratch //getTextArea public void
mousePressed(MouseEvent e) getTextArea().setEna
bled(getWritable()) setWritable(!getWritable())
//mousePressed public void
mouseReleased(MouseEvent e) public void
mouseClicked(MouseEvent e) public void
mouseEntered(MouseEvent e) public void
mouseExited(MouseEvent e) //class Notepad
Implement the method one needs the rest are
no-ops
128Driver main Notepad note MyFrame f
Notepad extends Panel Button toggle
TextArea scratch boolean bWritable
129Variation 2 Adapter Events (MouseAdapter)
import java.awt. import java.awt.event. class
Notepad extends Panel / NOTE NO INTERFACE!
/ Button toggle TextArea scratch
boolean bWritable public void
setWritable(boolean bWritable) this.bWritable
bWritable //setWritable public boolean
getWritable() return bWritable
//getWritable public TextArea
getTextArea() return scratch
//getTextArea
130 / . . . Continued from class Notepad extends
Panel / public Notepad() super()
this.setLayout (new BorderLayout()) scratch
new TextArea(20,20) Panel buttonPanel new
Panel() toggle new Button ("Freeze/Unfreeze")
buttonPanel.add(toggle) add(scratch,
BorderLayout.CENTER) add(buttonPanel,
BorderLayout.SOUTH) toggle.addMouseListener(new
MouseAdapter() public void
mousePressed(MouseEvent e)
getTextArea().setEnabled(getWritable())
setWritable(!getWritable()) )/
end of anonymous inner class / bWritable
false // constructor
Note use of anonymous inner class.
131Variation 3 Another Way!
- import java.awt.
- import java.awt.event.
- public class AnotherHandler extends MouseAdapter
- Notepad np
- public AnotherHandler(Notepad np)
- this.np np
- // Constructor
- public void mousePressed(MouseEvent e)
-
- np.getTextArea().setEnabled(np.getWritable())
- np.setWritable(!np.getWritable())
-
- // AnotherHandler
132Variation 3 Another Way
import java.awt. import java.awt.event. class
Notepad extends Panel / NOTE NO INTERFACE!
/ Button toggle TextArea scratch
boolean bWritable public void
setWritable(boolean bWritable) this.bWritable
bWritable //setWritable public boolean
getWritable() return bWritable
//getWritable public TextArea
getTextArea() return scratch
//getTextArea
133 / . . . Continued from "class Notepad extends
Panel" / public Notepad() super()
this.setLayout (new BorderLayout()) scratch
new TextArea(20,20) Panel buttonPanel new
Panel() toggle new Button ("Freeze/Unfreeze")
buttonPanel.add(toggle) add(scratch,
BorderLayout.CENTER) add(buttonPanel,
BorderLayout.SOUTH) AnotherHandler ah new
AnotherHandler(this) toggle.addMouseListener(ah)
bWritable false // constructor
134Variation 4 Semantic Events (ActionListener)
import java.awt. import java.awt.event. class
Notepad extends Panel implements ActionListener
Button toggle TextArea scratch
boolean bWritable public Notepad() super()
this.setLayout (new BorderLayout()) scratch
new TextArea(20,20) Panel buttonPanel new
Panel() toggle new Button ("Freeze/Unfreeze")
buttonPanel.add(toggle) add(scratch,
BorderLayout.CENTER) add(buttonPanel,
BorderLayout.SOUTH) toggle.addActionListener(thi
s) bWritable false // constructor
135/ . . . Continued from "class Notepad extends
Panel implements ActionListener" . .
. / public void setWritable(boolean
bWritable) this.bWritable bWritable
//setWritable public boolean
getWritable() return bWritable
//getWritable public TextArea getTextArea()
return scratch //getTextArea public
void actionPerformed (ActionEvent e)
getTextArea().setEnabled(getWritable()) setWr
itable(!getWritable()) //actionPerformed /
/class Notepad
136Event Handlers Final Review
This simple example shows that sometimes,
semantic event handlers perform the task
perfectly. In the drawing applet example, the
semantic event handler was unable to offer help.
In this example, it works perfectly, and was
easier to follow and implement. Note that a few
of the examples in this notepad demonstration
used anonymous inner classes. You will not be
required to use anonymous inner classes in CS2
however, they are used a lot and if y