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