COMP201 Java Programming
Download
Report
Transcript COMP201 Java Programming
COMP201 Java Programming
Part II: GUI Programming
Topic 9: Event Handling
Reading: Chapter 8
COMP201 Topic 9 / Slide 2
Outline
Introduction
Two examples
Adapter Classes
The AWT event hierarchy
Individual events: KeyEvents, MouseEvents
Separating GUI with Appl. Code
COMP201 Topic 9 / Slide 3
Event Handling Basics
Java automatically generates event objects when
Mouse or button clicked
Menu, checkbox, or text selected
Keyboard typed
Scrollbar adjusted
…..
It is up to the programmer to decide whether to do
anything or what to do when an event happens
(Programmer can create new event types.)
COMP201 Topic 9 / Slide 4
Event Handling Basics
The Java AWT event delegation model
Event source: an object that generates events
In order to capture interesting events and act accordingly, we
need to create listeners
A listener must be registered with an event source in order to listen
for events produced there.
A listener must implement a listener interface, which decides the
response to an event.
An event source can have multiple listeners and vice versa.
When an event occurs, event source sends event objects to all
registered listeners.
Listeners use information encapsulated in the event objects to
determine what to do.
COMP201 Topic 9 / Slide 5
Event Handling Basics
Event Object evt
Event Listener
Event Source
Any objects of class that implements Has to register its
own listeners
an appropriate listener interface
class Listener implements
ActionListener {
…
actionPerformed(Event evt) {…}
}
Source.addActionL
istener(Listener)
COMP201 Topic 9 / Slide 6
Example 1
A button that beeps when clicked (Beeper.java)
Create a GUI with one button
class BeeperFrame extends JFrame
{
public BeeperFrame()
{
setSize( 300, 200);
button = new JButton("Click Me");
getContentPane().add(button,
BorderLayout.CENTER);
}
Javax.swing.JButton
private JButton button;
has five constructors
}
Java.awt.Container
Adding button directly onto
contentPane. Bad programming style.
void add(Component)
COMP201 Topic 9 / Slide 7
Example 1
When a button is clicked, an ActionEvent object is produced
(java.awt.event.ActionEvent).
Listener for an ActionEvent: an object of a class that implements the
ActionListener Interface
class ClickListener implements ActionListener
{
public void actionPerformed(ActionEvent e) {
Toolkit.getDefaultToolkit().beep();
}
}
COMP201 Topic 9 / Slide 8
Example 1
Create a listener object and register it with the button:
class BeeperFrame extends JFrame
{ public BeeperFrame()
{
…
button = new JButton("Click Me");
button.addActionListener(new ClickListener());
}
}
The driver class:
public class Beeper
{ public static void main(String[] args)
{
BeeperFrame frame = new BeeperFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.show();
}
} //Beeper1.java
COMP201 Topic 9 / Slide 9
Example 2
Background color changes when we click on the buttons (run program).
Create three buttons
class ButtonPanel extends JPanel
{ public ButtonPanel()
{ yellowButton = new JButton("Yellow");
blueButton = new JButton("Blue");
redButton = new JButton("Red");
add(yellowButton);
add(blueButton);
add(redButton);
// create button actions
ColorAction yellowAction = new ColorAction(Color.yellow);
ColorAction blueAction = new ColorAction(Color.blue);
ColorAction redAction = new ColorAction(Color.red);
COMP201 Topic 9 / Slide 10
Example 2
// associate actions with buttons
yellowButton.addActionListener(yellowAction);
blueButton.addActionListener(blueAction);
redButton.addActionListener(redAction);
}
private JButton yellowButton;
private JButton blueButton;
private JButton redButton;
} // ButtonTest.java:
COMP201 Topic 9 / Slide 11
Example 2
Make an action listener that sets the panel's
background color.
private class ColorAction implements ActionListener
{
public ColorAction(Color c)
{
backgroundColor = c;
}
public void actionPerformed(ActionEvent event)
{
setBackground(backgroundColor);
repaint();
}
private Color backgroundColor;
}
COMP201 Topic 9 / Slide 12
Example 3
Make an action listener that sets the panel's
background color.
private class ColorAction implements ActionListener
{
public ColorAction(Color c)
{
backgroundColor = c;
}
public void actionPerformed(ActionEvent event)
{
setBackground(backgroundColor);
repaint();
}
private Color backgroundColor;
}
COMP201 Topic 9 / Slide 13
Adapter Classes
Illustrate the concept of Adapter classes using
WindowEvents
With JDK1.3, we can terminate program when a window is closed
using
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Without it, program won’t terminate when window is closed. Try
FirstTest.java:
COMP201 Topic 9 / Slide 14
FirstTest
public class FirstTest
{ public static void main(String[] args)
{ JFrame frame = new FirstFrame();
frame.show();
}
}
class FirstFrame extends JFrame
{ public FirstFrame()
{ setTitle("FirstFrame");
setSize(300, 200);
}
}
COMP201 Topic 9 / Slide 15
Adapter Classes
Let’s try to fix it.
When user tries to close window, FirstFrame
object (window) generates a WindowEvent object.
Create a listener object that listens for
WindowEvent and terminates the program when
user closes the window.
The object must belong to a class (call it
Teminator) that implements the
WindowListener Interface.
COMP201 Topic 9 / Slide 16
Adapter Classes
The WindowListener Interface has seven methods, one for
each distinct event that can happen to a window
class Terminator implements WindowListener
{ public void windowClosing(WindowEvent e)
{System.exit(0);}
public void windowClosed(WindowEvent e) {};
public void windowIConified(WindowEvent e) {};
public void windowOpened(WindowEvent e) {};
public void windowDeiconified(WindowEvent e) {};
public void windowActivated(WindowEvent e) {};
public void windowDeactivated(WindowEvent e) {};
}
We are only interested in one event: user closing window.
COMP201 Topic 9 / Slide 17
Adapter Classes
Register listener with event source.
class FirstFrame extends JFrame
{ public FirstFrame()
{ setTitle("FirstFrame");
setSize(300, 200);
addWindowListener( new Terminator() );
}
} //CloseableW1.java
COMP201 Topic 9 / Slide 18
Adapter Classes
Keying in code for six do-nothing method is tedious.
Java provides companion adapter class for each AWT
listener interface that has more than one method.
The adapter class implements all methods to do
nothing.
We can extend the adapter by refining only methods
that correspond to interesting events.
COMP201 Topic 9 / Slide 19
Adapter Classes
The adaptor for WindowListener interface is called
WindowAdaptor.
Using the adapter, we can rewrite Terminator class
as follows:
class Terminator extends WindowAdapter
{ public void windowClosing(WindowEvent e)
{ System.exit(0);
}
}
CloseableW2.java
COMP201 Topic 9 / Slide 20
Adapter Classes
So far, we have
class FirstFrame extends JFrame
{ public FirstFrame()
{ setTitle("FirstFrame");
setSize(300, 200);
addWindowListener( new Terminator() );
}
}
class Terminator extends WindowAdaptor
{ public void windowClosing(WindowEvent e)
{ System.exit(0);
}
}
Making Terminator an anonymous inner class (replace its
usage in FirstFrame with its definition.)
COMP201 Topic 9 / Slide 21
Adapter Classes
The current program:
class FirstFrame extends JFrame
{ public FirstFrame()
{ setTitle("FirstFrame");
setSize(300, 200);
addWindowListener( new WindowAdapter()
{ public void windowClosing(WindowEvent e)
{ System.exit(0);
}
} );
}
} //CloseableW3.java
This is exactly what we have in the textbook using JDK1.2.
COMP201 Topic 9 / Slide 22
The AWT Event Hierarchy
EventObject
…….
Action
Event
Container
Event
java.util
java.awt.event
AWTEvent
Adjustment
Event
Component
Event
Item
Event
Text
Event
Input
Event
Paint
Event
Window
Event
Focus
Event
Key
Event
Mouse
Event
Programmer no need
to worry about paint
events
COMP201 Topic 9 / Slide 23
The AWT Event Hierarchy
11 listener interfaces in java.awt.event
ActionListener
KeyListener*
AdjustmentListener
MouseListener*
ComponentListener*
MouseMotionListener*
ContainerListener*
TextListener
FocusListener*
WindowListener*
ItemListener
*: Listeners that have corresponding adapters
COMP201 Topic 9 / Slide 24
The AWT Event Hierarchy
Semantic Events: What user does
ActionEvent (button click, menu selection)
AdjustmentEvent (adjusting scroll bar)
ItemEvent (selection from checkbox or list items)
TextEvent (the contents of a text field or text area
were changed)
Additional events (like MenuEvent, ChangeEvent)
can be found in javax.swing.event. They are
associated with Swing components and easy to
handle. Will discuss some in the next topic.
COMP201 Topic 9 / Slide 25
The AWT Event Hierarchy
Low-Level Events: facilitate semantic events
ComponentEvent (component resized, moved,
shown, or hidden)
A component is a user interface elements such as
button, text field, scrollbar, panel, frame
ComponentEvent is the ancestor of all low-level
event classes
FocusEvent (component get focus)
ContainerEvent (a component has been added or
removed. Programmers no need to worry about it)
A container is a screen area or component that can
contain components. E.g. window, panel
COMP201 Topic 9 / Slide 26
The AWT Event Hierarchy
Low-Level Events: facilitates semantic events
KeyEvent (key pressed or released)
MouseEvent (mouse button pressed, released,
moved, or dragged)
WindowEvent (window activated, deactivated,
iconified, deiconified, or closed)
Will discuss KeyEvent and MouseEvent
COMP201 Topic 9 / Slide 27
Individual Events/KeyEvent
Only one component can have the focus at a time
Only the component that has focus can receive
keystrokes
A component gains focus if the user clicks the mouse
inside it.
Or TAB/SHIT-TAB key can be used to traverses
components which can receive input focus.
FocusEvent is generated when a component gains
focus or loses focus. Refer to textbook for how to
handle focus events.
COMP201 Topic 9 / Slide 28
Individual Events/ KeyEvent
Methods of java.awt.Component
void requestFocus(): Moves focus to this
component
boolean isFocusTraversible(): Tells
whether a component can be reached by using TAB
or SHIFT-TAB
void transferFocus(): Transfer focus to the
next component in the traversal order.
COMP201 Topic 9 / Slide 29
Individual Events/ KeyEvent
Java distinguish between characters and virtual key code
– “A” and “a” have the same code VK_A
– There is no VK_a !!
– More examples: VK_COMMA, VK_PERIOD,
VK_OPEN_BRACKET, VK_SHIFT ...
KeyEvent objects are generated by component with focus
when a key is pressed or released.
Typing “a” generates three KeyEvent objects
keyPressed VK_A (Virtual key code)
keyTyped “a”
keyReleased VK_A (Virtual key code)
COMP201 Topic 9 / Slide 30
Individual Events/ KeyEvent
Methods in the KeyListener Interface:
keyPressed(KeyEvent e)
(what to do when VK_A pressed?)
keyReleased(KeyEvent e)
(what to do when VK_A released?)
keyTyped(KeyEvent e)
(what to do when “a” is typed?)
Methods of java.awt.event.KeyEvent
Class:
–
–
–
getKeyCode() to get back virtual key code.
getKeyChar() to get back the key character
….
COMP201 Topic 9 / Slide 31
Individual Events/ KeyEvent
Example: Sketch.java
Move with either cursor keys or “h”, “j”, “k”, “l” keys
Move faster when SHIFT is pressed
public SketchPanel()
{
last = new Point2D.Double(100, 100);
lines = new ArrayList();
KeyHandler listener = new KeyHandler();
addKeyListener(listener);
}
public boolean isFocusTraversable() { return true; }
…
}
We need this because normally a panel
cannot get keyboard focus
COMP201 Topic 9 / Slide 32
Individual Events/ KeyEvent
Pressing cursor keys:
public void keyPressed(KeyEvent event)
{
int keyCode = event.getKeyCode();
// set distance
int d;
if (event.isShiftDown())
d = LARGE_INCREMENT;
else
d = SMALL_INCREMENT;
// direction of move
if (keyCode == KeyEvent.VK_LEFT) add(-d, 0);
else if (keyCode == KeyEvent.VK_RIGHT) add(d, 0);
else if (keyCode == KeyEvent.VK_UP) add(0, -d);
else if (keyCode == KeyEvent.VK_DOWN) add(0, d);
}
Note: Can also use getModifiers of InputEvent or
getKeyModifiers of KeyEvent to find out whether SHIFT is down
COMP201 Topic 9 / Slide 33
Individual Events/ KeyEvent
Typing keys “h”. “j”, “k”, “l”:
public void keyTyped(KeyEvent event)
{ char keyChar = event.getKeyChar();
int d; // distance of move
if (Character.isUpperCase(keyChar))
{ d = LARGE_INCREMENT;
keyChar = Character.toLowerCase(keyChar);
}
else d = SMALL_INCREMENT;
// direction of move
if (keyChar == 'h') add(-d, 0);
else if (keyChar == 'l') add(d, 0);
else if (keyChar == 'k') add(0, -d);
else if (keyChar == 'j') add(0, d);
}
Note: Can also use getModifiers of InputEvent or getKeyModifiers
of KeyEvent to find out whether upper case or lower case
COMP201 Topic 9 / Slide 34
Individual Events/ MouseEvent
Just want to know whether a button or menu is clicked?
No need to use mouse events explicitly. Instead use
ActionEvents generated by button or menu.
For drawing with mouse, mouse events are important.
MouseEvent objects generated by components where
mouse cursor is located
COMP201 Topic 9 / Slide 35
Individual Events/ MouseEvent
Two listener interfaces
MouseListener
– mousePressed(MouseEvent evt)
– mouseReleased(MouseEvent evt)
– mouseClicked(MouseEvent evt)
MouseMotionListener
– mouseMoved(MouseEvent evt)
– mouseDragged(MouseEvent evt)
COMP201 Topic 9 / Slide 36
Individual Events/Mouse Events
Getting information about MouseEvents
int getX(), int getY() to get the x , y coordinates of mouse
pointer.
Point getPoint() to get coordinates of mouse pointer as a
Point object
int getClickCount() to get number of consecutive clicks.
int getModifiers() to find out, among other things, which
mouse button is clicked.
COMP201 Topic 9 / Slide 37
Individual Events/ MouseEvent
MouseTest.java -- place, move, and erase squares
class MousePanel extends JPanel
{
}
public void paintComponent(Graphics g)
{ super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
// draw all squares
for (int i = 0; i < squares.size(); i++)
g2.draw((Rectangle2D)squares.get(i));
}
private static final int SIDELENGTH = 10;
private ArrayList squares;
private Rectangle2D current;
…
COMP201 Topic 9 / Slide 38
Individual Events/ MouseEvent
MousePanel –Basic methods
class MousePanel extends JPanel
{…
// Finds the first square containing a point.
public Rectangle2D find(Point2D p){…}
// Adds a square to collection
public void add(Point2D p){…}
// Removes a square to collection
public void remove(Point2D p){…}
…
}
COMP201 Topic 9 / Slide 39
Individual Events/ MouseEvent
MousePanel provides MouseEvents, which will be handled by
MouseHandler and MouseMotionHandler
class MousePanel extends JPanel
{
…
public MousePanel()
{
squares = new ArrayList();
current = null;
addMouseListener(new MouseHandler());
addMouseMotionListener(
new MouseMotionHandler());
} …
}
COMP201 Topic 9 / Slide 40
Individual Events/ MouseEvent
MouseHandler is an inner class of MousePanel
class MousePanel extends Jpanel
{
private class MouseHandler extends MouseAdapter
{
public void mousePressed(MouseEvent event)
{
// add a new square if the cursor isn't inside a square
current = find(event.getPoint());
if (current == null)
add(event.getPoint()); }
public void mouseClicked(MouseEvent event)
{ // remove the current square if double clicked
current = find(event.getPoint());
if (current != null && event.getClickCount() >= 2)
remove(current);
…
COMP201 Topic 9 / Slide 41
Individual Events/ MouseEvent
MouseMotionHandler is also an inner class of MousePanel
class MousePanel extends Jpanel
{
private class MouseMotionHandler
implements MouseMotionListener
{
public void mouseMoved(MouseEvent event){…}
public void mouseDragged(MouseEvent event)
{ if (current != null)
{ int x = event.getX(); int y = event.getY();
// drag the rectangle to center it at (x, y)
current.setFrame(x - SIDELENGTH/2,
y - SIDELENGTH/2, SIDELENGTH, SIDELENGTH);
repaint();
}
}
COMP201 Topic 9 / Slide 42
Separating GUI & Appl Code
Suppose we want to change background color by doing one
of the following:
Click on one of the buttons
Select a color from a menu
Press a key :
ctrl B = blue, ctrl Y = Yellow, ctrl R = red
Separating GUI & Appl code: Deal with color change
command in a uniformed way, no matter how the command
is invoked.
Make an ColorAction object for each command (appl.)
Make the object listener to all events that trigger the
command (GUI)
COMP201 Topic 9 / Slide 43
Action interface
Javax.swing.Action interface: An action is an
object that encapsulates the following:
• A description of the commend (as a text string and
an optional icon)
• Parameters that are necessary to carry out the
command (such as the requested color in our
example).
COMP201 Topic 9 / Slide 44
Separating GUI & Appl Code
• Javax.swing.Action interface extends the
interface ActionListener
–
–
–
–
–
–
–
void actionPerformed(ActionEvent evt)
void setEnabled(boolean b)
boolean isEnabled()
void putValue(String key, Object value)
Object getValue(String key)
void addPropertyChangeListener(…)
void removePropertyChangeListener(…)
COMP201 Topic 9 / Slide 45
Separating GUI & Appl Code
• void putValue(String key, Object value)
• Object getValue(String key)
– Store and retrieve name/value pair in the action object e.g.,
action’s name, action’s icon
– Some useful pre-defined keys: Action.NAME, Action.SMALL_ICON
Action.putValue(Action.Name, “Blue”);
Action.putValue(Action.SMALL_ICON,
new ImageIcon(“Blue-ball.gif”));
• void addPropertyChangeListener(…)
• void removePropertyChangeListener(…)
– Monitoring the properties of action object (e.g. if action name
changes, menu item should also change).
COMP201 Topic 9 / Slide 46
Separating GUI & Appl Code
• Class AbstractAction is a default
implementation of Action
– The only abstract method is actionPerformed()
• Instead of implementing Action, you can
simply extending AbstractAction (similar to
adapter class)
COMP201 Topic 9 / Slide 47
Separating GUI & Appl Code
Use of class AbstractAction in the background
color change example
Define ColorAction class as an inner class of
ActionPanel:
.class ColorAction extends AbstractAction
{ public ColorAction(String name, Icon icon,
Color c)
{ putValue(Action.NAME, name);
putValue(Action.SMALL_ICON, icon);
putValue("Color", c);
}
New property with value c
//actionPerformed
}
COMP201 Topic 9 / Slide 48
Separating GUI & Appl Code
class ColorAction extends AbstractionAction
{ // constructor here
public void actionPerformed(ActionEvent evt)
{ Color c = (Color)getValue("Color");
setBackground(c);
repaint();
}
}
Apply setBackGround(c) & repaint() to this.
Create three Action objects:
Action blueAction =
new ColorAction("Blue",
new ImageIcon("blue-ball.gif"),
Color.blue);
Action yellowAction =
new ColorAction("Yellow",
new ImageIcon("yellow-ball.gif"),
Color.yellow);
Action redAction =
new ColorAction("Red",
new ImageIcon("red-ball.gif"),
Color.red);
COMP201 Topic 9 / Slide 50
Separating GUI & Appl Code
Associate those actions with buttons by invoke JButton
constructor which takes an Action object
Add those buttons to this JPanel
add(new JButton(yellowAction));
add(new JButton(blueAction));
add(new JButton(redAction));
COMP201 Topic 9 / Slide 51
Separating GUI & Appl Code
Keystrokes are delivered to the component that has focus.
Each of the three buttons and the panel can have focus. So we
need to deal with keystrokes in each of the three buttons and the
panel
It is implemented in two steps
1.
Use one of the three InputMaps of JComponent (a
superclass of JPanel) to associate keystrokes with some
arbitrary objects.
2.
A second map, implemented by ActionMap class maps
those objects to actions.
COMP201 Topic 9 / Slide 52
Separating GUI & Appl Code
Every Jcomponent has three InputMaps that map KeyStroke
objects to actions:
1. WHEN_FOCUSED
When this component has keyboard focus
2. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
When this component contains the component that has
keyboard focus
3. WHEN_IN_FOCUSED_WINDOW
When this component is contained in the same window as
the component that has keyboard focus
COMP201 Topic 9 / Slide 53
Separating GUI & Appl Code
// Obtain an input map with getInputMap method
InputMap imap =
panel.getInputMap(JComponent.WHEN_FOCUSED);
//In the map associate "ctrl Y” to an action key “panel.yellow”
imap.put(KeyStroke.getKeyStroke("ctrl Y"),
"panel.yellow");
Every Jcomponent also has one ActionMap to associate some objects
to Actions.
// To obtain the action map:
ActionMap amap = panel.getActionMap().
// link the action key to the real action
amap.put("panel.yellow", yellowAction);
// associate the ctrl_Y, ctrl_B, and ctrl_R with action keys
InputMap imap = getInputMap( // since 1.3
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
imap.put(KeyStroke.getKeyStroke("ctrl Y"), "panel.yellow");
imap.put(KeyStroke.getKeyStroke("ctrl B"), "panel.blue");
imap.put(KeyStroke.getKeyStroke("ctrl R"), "panel.red");
// associate action keys with actions
ActionMap amap = getActionMap();
amap.put("panel.yellow", yellowAction);
amap.put("panel.blue", blueAction);
amap.put("panel.red", redAction);
The action will be triggered by keystroke if the component pointed
at by mouse and the the component that has focus are in the same
window.
In
our example, keystrokes can trigger actions if mouse cursor
inside window
COMP201 Topic 9 / Slide 55
Separating GUI & Appl Code
Steps to carry out the same action in response to a button, a menu item, or
a keystroke:
1.
Make a class that extends the AbstractAction.
2.
3.
4.
Make an object of that class.
Construct a button or menu item from that object. The constructor will
read the label text and icon from the action object.
For action that can be triggered by keystrokes
1.
Locate the top-level component of the window, such as a panel that
contains all other components.
2.
Get the when_ancestor_of_focused_component input map of
the top-level component. Make a KeyStroke object for the
desired keystroke. Make an action key object, such as a string that
describes your action. Add the pair(keystroke, action key ) into the
input map.
3.
Get the action map of the top-leve component. Add the pair (action
key, action object) into the map.