Header javaperspective.com
JavaPerspective.com  >   Intermediate Tutorials  >   5. Graphical User Interfaces  >   5.3. Event listeners

5.3. Event listeners
Last updated: 1 February 2013.

This tutorial will show you how to make a button react to user clicks and more generally, how to add event listeners to components.

When you click a button contained in a GUI, an event is fired by the button. Each component in the Swing class hierarchy can fire events.

An event listener is an object that listens to events received from components. It is an object that implements a subinterface of EventListener. Events fired by a component can be received by a listener only if that listener has been registered by the component.

For example, a button (an instance of the class JButton) can register an event listener by invoking the method addActionListener(ActionListener l). The event listener (the argument l) is an object that implements the interface ActionListener which is itself a subinterface of the interface EventListener. The following sample creates a window containing a button that registers an event listener. Whenever the button is clicked, the message "button clicked" is printed to the standard output:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public final class FirstFrame extends JFrame{

   
public FirstFrame() {
         
setTitle("My first JFrame");
          setSize
(300, 200);
          setLocation
(200, 100);
          setResizable
(false);
         
         
// Create the button
         
JButton button = new JButton("Button");
         
         
// Register the action listener
         
button.addActionListener(new ActionListener() {
               
public void actionPerformed(ActionEvent e) {
                     
System.out.println("button clicked");
               
}
          })
;
         
         
// Add the button to the JFrame
         
add(button);
         
          setDefaultCloseOperation
(JFrame.EXIT_ON_CLOSE);
          setVisible
(true);
   
}
}

As you can see, the argument of the method addActionListener is an anonymous class because it is used only once. Event listeners are usually implemented as anonymous classes since they are often used only once.

The method actionPerformed(ActionEvent e) is the only method of the interface ActionListener. It is implemented by the anonymous class and contains the code that is executed when the button is clicked. The ActionEvent argument provides several methods like getSource which returns the object that fired the event (the button in this case).

You might be aware that it is good programming practice to separate the code that builds a GUI from the class containing the main method. The class App shown below contains a main method that displays the window:

import javax.swing.SwingUtilities;

public final class App {

   
public static void main(String[] args){
         
SwingUtilities.invokeLater(new Runnable() {
               
public void run() {
                     
new FirstFrame();
               
}
          })
;
   
}
}

The code above deserves a comment. When you create a GUI with Swing, a thread known as the event dispatching thread is responsible for all the drawing and event handling. In particular, if the event dispatching thread is performing a complex or time consuming task, the GUI freezes and does not respond to button clicks or any other handled events until the task is completed. There is only one event dispatching thread and every code that acts upon the GUI's components must be executed by that thread.

However, as you might already know, the code contained in a main method runs in its own separate thread. But since the main method in the class App shown above starts the drawing of the GUI, it should be executed by the event dispatching thread. Otherwise, exceptions may occur and the GUI is likely to behave unpredictably.

The recommended way to hand over the code contained in the main method to the event dispatching thread is to call the static method invokeLater(Runnable doRun) provided by the class SwingUtilities. In fact, invokeLater(Runnable doRun) schedules the execution of the specified Runnable implementation on the event dispatching thread. In the main method shown above, I passed to the method invokeLater an anonymous class that implements the interface Runnable. The code that starts the drawing of the GUI is in the method run.

Separating the code that builds a GUI from the class containing the main method is particularly essential when dealing with a large project that comprises numerous subwindows. There is usually at least one class per subwindow. In that case, the main method is much easier to find by other developers if it belongs to a separate class (named App or Main) and possibly to a separate package. However, the next tutorials will provide relatively simple and concise examples. Consequently, in the next tutorials, I will not separate the class containing the main method from the code that builds the GUI.


Listening to multiple events at a time

The event listener described above only listens to button clicks. However, a button can fire other types of events and register listeners for those events as well. In fact, every component can fire a set of events. One easy way to know what kinds of events a component can fire is to search in the component's API documentation for methods whose names look something like add...Listener. When searching in the component's API documentation, remember that you can also search in the super classes.

For example, the super classes of the class JButton provide other add...Listener methods, such as the method addMouseMotionListener(MouseMotionListener l) provided by the class Component which registers a listener that receives events when the mouse is moved or dragged on the button. The sample shown below provides code to listen simultaneously to events that are fired when the user clicks the button, moves the mouse or drags it over the button:

import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public final class FirstFrame extends JFrame{

   
public FirstFrame() {
         
setTitle("My first JFrame");
          setSize
(300, 200);
          setLocation
(200, 100);
          setResizable
(false);

         
// Create the button
         
JButton button = new JButton("Button");

         
// Register the action listener
         
button.addActionListener(new ActionListener() {
               
public void actionPerformed(ActionEvent e) {
                     
System.out.println("button clicked");
               
}
          })
;

         
// Register the mouse motion listener
         
button.addMouseMotionListener(new MouseMotionListener() {
               
public void mouseMoved(MouseEvent e) {
                     
Point mousePosition = getMousePosition();
                     
if(mousePosition != null)
                           
System.out.println("mouse moved : X = " + mousePosition.getX() + ", Y = " + mousePosition.getY());
               
}

               
public void mouseDragged(MouseEvent e) {
                     
Point mousePosition = getMousePosition();
                     
if(mousePosition != null)
                           
System.out.println("mouse dragged : X = " + mousePosition.getX() + ", Y = " + mousePosition.getY());
               
}
          })
;

         
// Add the button to the JFrame
         
add(button);

          setDefaultCloseOperation
(JFrame.EXIT_ON_CLOSE);
          setVisible
(true);
   
}
}

The interface MouseMotionListener has two methods that are implemented by an anonymous class to print to the standard output the position of the mouse when it is moved or dragged in the button's coordinate space. The method getMousePosition that is used here is provided by the class Component.


Adapter classes

If an event listener interface has numerous methods, implementing all of them can be a chore, especially if you are interested in implementing only a few methods. To avoid having to implement all the methods of an event listener interface, you can use an adapter class. An adapter class is a class that implements an event listener interface without doing anything in the methods implementations. The Java API provides adapter classes for most event listener interfaces that have more than one method (the names of those adapter classes simply end with Adapter). When using an adapter class, you only need to override the methods of interest. As an example, if you are only interested in listening to mouse drag events, you can use the MouseMotionAdapter class this way:

button.addMouseMotionListener(new MouseMotionAdapter() {
   
public void mouseDragged(MouseEvent e) {
         
Point mousePosition = getMousePosition();
         
if(mousePosition != null)
               
System.out.println("mouse dragged : X = " + mousePosition.getX() + ", Y = " + mousePosition.getY());
   
}
})
;


You are here :  JavaPerspective.com  >   Intermediate Tutorials  >   5. Graphical User Interfaces  >   5.3. Event listeners
Next tutorial :  JavaPerspective.com  >   Intermediate Tutorials  >   5. Graphical User Interfaces  >   5.4. Layouts

Copyright © 2013. JavaPerspective.com. All rights reserved.  ( Terms | Contact | About ) 
Java is a trademark of Oracle Corporation
Image 1 Image 2 Image 3 Image 4 Image 5 Image 6 Image 7