240 likes | 271 Vues
Learn how to implement event listeners in SWING components using ActionListener interface. Create responsive buttons and windows in Java with practical examples.
E N D
Event Handling and Listeners in SWING The practice of event handling
Implementing listeners • To write an Action Listener, follow the steps given below: • Declare an event handler class and specify that the class either implements an ActionListener interface or extends a class that implements an ActionListener interface. • For example: public class MyClass implements ActionListener { • Register an instance of the event handler class as a listener on one or more components. • For example: 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... } • Three key bits of code • 1) add interface • 2) register • 3) handle • Components can have multiple listeners • 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) { 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 void windowOpened(WindowEvent e) {} public void windowActivated(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowDeactivated(WindowEvent e) {} public void windowClosed(WindowEvent e) {} Set up things: public class AL extends Frame implements windowListener,ActionListener { TextField text = new TextField(20); Button b; private int numClicks = 0;
Implementing listeners (2) We would like to handle the button-click event, so we add an action listener to the button b as below: b = new Button("Click me"); b.addActionListener(this); 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) { 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 void windowOpened(WindowEvent e) {} public void windowActivated(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowDeactivated(WindowEvent e) {} public void windowClosed(WindowEvent e) {}
Implementing listeners (2) public void actionPerformed(ActionEvent e) { numClicks++; text.setText("Button Clicked " + numClicks + " times"); Now, when the user clicks the Button b, the button fires an action event which invokes the action listener's actionPerformed method. 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) { 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 void windowOpened(WindowEvent e) {} public void windowActivated(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowDeactivated(WindowEvent e) {} public void 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 • ActionListener • CaretListener • ChangeListener • DocumentListener • ItemListener • ListSelectionListener • WindowListener • etc. • See: http://java.sun.com/docs/books/tutorial/uiswing/events/eventsandcomponents.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