Lecture X – Event Handling and Listeners

Download Report

Transcript Lecture X – Event Handling and Listeners

Event Handling and
Listeners in SWING
The practice of event handling
Some swing component
events and listeners
Act that results in event
Listener
User clicks a button, presses return while typing ActionListener
in a text field, or chooses a menu item
User closes a window
WindowListener
User presses a mouse button while the cursor is
over a component
MouseListener
User moves the mouse over a component
MouseMotionListener
Component becomes visible
ComponentListener
Component gets the keyboard focus
FocusListener
Table or list selection changes
ListSelectionListener
Implementing
listeners
To write an Action Listener, follow the steps given below:

1.Three
Declare
event
handler class and specify that the class
keyanbits
of code
either implements an ActionListener interface or extends a
• class
1) add
interface
that
implements an ActionListener interface.
• 2) register
Forhandle
example:
• 3)

Components
can have multiple listeners
Register an instance of the event handler class as a listener
2.
on one or more components.
For example:
3.

public class MyClass implements ActionListener {
someComponent.addActionListener(instanceOfMyClass);
Include code that implements the methods in listener
interface.
For example:
public void actionPerformed(ActionEvent e) { ...//code that reacts to the action... }
A simple
JButton
ActionListener…
Implementing listeners (2)
public class myClass … implements ActionListener {
…
// where setting up occurs (e.g. constructor)
JButton button = new JButton(“I am a button”);
button.addActionListener(this);
…
public void actionPerformed(ActionEvent e) {
…
// respond to event
} // end response method
} // end class
Implementing listeners (2)
import java.awt.*;
import java.awt.event.*;
public class AL extends Frame implements WindowListener,ActionListener {
TextField text = new TextField(20);
Button b;
private int numClicks = 0;
public static void main(String[] args) {
AL myWindow = new AL("My first window");
myWindow.setSize(350,100);
myWindow.setVisible(true);
}
public AL(String title) {
Set up things:
super(title);
setLayout(new FlowLayout());
addWindowListener(this);
b = new Button("Click me");
add(b);
add(text);
b.addActionListener(this);
public class AL extends Frame implements windowListener,ActionListener {
TextField text = new TextField(20);
Button b;
private int numClicks = 0;
}
public void actionPerformed(ActionEvent e) {
numClicks++;
text.setText("Button Clicked " + numClicks + " times");
}
public void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
public
public
public
public
public
public
void
void
void
void
void
void
windowOpened(WindowEvent e) {}
windowActivated(WindowEvent e) {}
windowIconified(WindowEvent e) {}
windowDeiconified(WindowEvent e) {}
windowDeactivated(WindowEvent e) {}
windowClosed(WindowEvent e) {}
We would like to handle the button-click event,
so we add an action listener to the button b as
below:
Implementing listeners (2)
import java.awt.*;
import java.awt.event.*;
public class AL extends Frame implements WindowListener,ActionListener {
TextField text = new TextField(20);
Button b;
private int numClicks = 0;
b = new Button("Click me");
b.addActionListener(this);
public static void main(String[] args) {
AL myWindow = new AL("My first window");
myWindow.setSize(350,100);
myWindow.setVisible(true);
}
public AL(String title) {
super(title);
setLayout(new FlowLayout());
addWindowListener(this);
b = new Button("Click me");
add(b);
add(text);
b.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
numClicks++;
text.setText("Button Clicked " + numClicks + " times");
}
public void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
public
public
public
public
public
public
void
void
void
void
void
void
windowOpened(WindowEvent e) {}
windowActivated(WindowEvent e) {}
windowIconified(WindowEvent e) {}
windowDeiconified(WindowEvent e) {}
windowDeactivated(WindowEvent e) {}
windowClosed(WindowEvent e) {}
public void actionPerformed(ActionEvent e)
{
numClicks++;
text.setText("Button Clicked " + numClicks + " times");
Implementing listeners (2)
import java.awt.*;
import java.awt.event.*;
public class AL extends Frame implements WindowListener,ActionListener {
TextField text = new TextField(20);
Button b;
private int numClicks = 0;
Now, when the user clicks the Button b, the button fires an
action event which invokes the action listener's
actionPerformed method.
public static void main(String[] args) {
AL myWindow = new AL("My first window");
myWindow.setSize(350,100);
myWindow.setVisible(true);
}
public AL(String title) {
super(title);
setLayout(new FlowLayout());
addWindowListener(this);
b = new Button("Click me");
add(b);
add(text);
b.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
numClicks++;
text.setText("Button Clicked " + numClicks + " times");
}
public void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
public
public
public
public
public
public
void
void
void
void
void
void
windowOpened(WindowEvent e) {}
windowActivated(WindowEvent e) {}
windowIconified(WindowEvent e) {}
windowDeiconified(WindowEvent e) {}
windowDeactivated(WindowEvent e) {}
windowClosed(WindowEvent e) {}
Types of event listeners

Global component listeners
• may be used for any Swing components

Types of global listeners





ComponentListener (changes in size, position, visibility)
FocusListener (whether ability for keyboard input)
KeyListener (key press events, only with focus)
MouseListener (clicks and movement into/out of
component area)
MouseMotionListener (changes in position over
component)
Types of event listeners (2)

Component-specific listeners
• relevant to specific components’ actions
• Types








See:
ActionListener
CaretListener
ChangeListener
DocumentListener
ItemListener
ListSelectionListener
WindowListener
etc.

http://java.sun.com/docs/books/tutorial/uiswing/events/eventsandcompo
nents.html
Working with event listeners

Getting event information

Low-level events

Semantic events

Adapters for event handling

Inner classes for event handling
Getting event information



EventObject class - use sub classes of this to
determine what’s happened.
Get the firing object with getSource();
Actual event classes sometimes have specific
types
• e.g. the ComponentListener uses a sub-class of
EventObject : ComponentEvent that has
getComponent();

Event classes may define methods that return
more information
• e.g. ActionEvent has a method for getting modifiers
(Shift, Alt, Ctrl)
Low-level and semantic events

Low-level events - window-system level
• e.g. mouse, key, component, container, focus,
window
• trigger component-independent

Semantic events
• everything else! – e.g. action, item, list selection
• trigger can differ by component

e.g. button click and textfield ‘return’ action events
Low-level and semantic events

Listen for semantic events whenever possible
• Gives robust and portable code

eg Button - listen for action event rather than mouse
event. Means that button responds to keyboard
shortcuts.
• Compound components

eg combo box - no real way of guaranteeing low level
listeners on all look and feel specific components used to
form the compound component.
Adapters for event handling

Classes which implement listener
interfaces must implement all listener
methods
• e.g. MouseListener has 5 methods:
mouseClicked, mouseReleased,
mousePressed, mouseEntered, mouseExited

This leads to cluttered code
• Say you only want mouseClicked to do
something then all others have to be
implemented but empty

Alternative….
Adapters for event handling (2)

... is to extend a MouseAdapter class
• inherits empty definitions of all five
mouseListener methods. Eg:
public class MyClass extends MouseAdapter {
...
someObject.addMouseListener(this);
...
public void mouseClicked(MouseEvent e) {
//Event handler implementation goes here...
}
}
Inner classes for event handling

Don’t want to / cant inherit from an
adapter class?
• there’s no multiple inheritance in Java

eg can’t extend JPanel AND MouseAdapter
• Solution: use an inner class

public class MyClass extends JPanel {
…
anObject.addMouseListener(new myAdapter());
…
class myAdapter extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
// blah
} // end mouseClicked
} // end inner class
} // end MyClass
Inner classes for event handling
(2)

Anonymous classes • used to simplify code
• good when only 1 instance will ever be needed

public class MyClass extends JPanel {
...
someObject.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
//Event handler implementation goes here
}
});
...
}
Threads and Swing

Why use them?
• Improved perceived performance
• Can remove time consuming task from
event thread to keep GUI responsive
• Initialisation of program so GUI appears
faster

Potential problems
• Deadlock the application if access any
realised swing components from non event
threads.
Threads and Swing

Remember the rule:
• Once a Swing component has been realised, all code
that might affect or depend on the state of that
component should be executed in the event-dispatching
thread.

If code does not need to be in event
thread then:
public void actionPerformed(ActionEvent e) {
final SwingWorker worker = new SwingWorker() {
public Object construct() {
//---code that might take a while to execute is here...
return someValue;
}
};
worker.start(); //required for SwingWorker 3
}
Threads and Swing

invokeLater()
• requests that event thread runs certain
code
• can be called from any thread
• code goes in run method of Runable object
• returns immediately without waiting for
event thread to execute code.
Runnable updateAComponent = new Runnable() {
public void run() {component.doSomething(); }
};
SwingUtilities.invokeLater(updateAComponent);
Threads and Swing (4)

invokeAndWait()
• identical to invokeLater() except doesn’t
return till event thread has finished
executing the code.
• Should use this if possible - less chance of
deadlock.
void showHelloThereDialog() throws Exception {
Runnable showModalDialog = new Runnable() {
public void run() {
JOptionPane.showMessageDialog(myMainFrame,
"Hello There");
}
};
SwingUtilities.invokeAndWait(showModalDialog);
}
Summary



Implementing event listeners
Types of event listeners
Handling event listeners
• getting event information
• low-level and semantic events
• adapters
• inner classes - named and anonymous

Threads
A simple Swing program

Uses components in containers
Lays components out correctly
Listens for events

An example:


• SwingExample.java (revisited)…
• Code on Course Website…
A (Slightly) More Complex
Swing program


Uses components in containers (again)
Lays components out correctly (again but more complex)

Listens for events - Multiple listeners

Another example:
• SwingExample2.java