Building the Image Button
File:
ImageButton.java
Contents
Overview
The ImageButton is the base class that provides core functionality for all of the buttons used in the controller.
The ImageButton
class is derived from java.awt.Component (see diagram right).
It implements several methods that provide basic functionality such as
retrieving an image, setting an image, removing an image and painting
itself. It also responds to MouseRelease messages.
This class declares two abstract methods, handleRollover( ) and handleMousePressed( ), which are implemented in the derived-class RolloverButton.
The RolloverButton class is responsible for swapping images when the button is clicked, and when the mouse is hovering over the button. For more information on this class, see Building the Rollover Button.
There is a third and final tier which consists of three classes that derive from RolloverButton: ForwardButton,
BackwardButton, and PlayPauseButton.
These classes are extremely simple and implement a single method that specifies which images to use for the button state. These classes are explained in more detail later.
This hierarchy allows us to better group related functionality together with common behaviors in the base class and more specific behaviors in the derived classes. This allows for a much cleaner and coherent API, and demonstrates the power of object-oriented programming.
Steps to Follow
Back to top
The ImageButton is an abstract class. That means that it cannot be directly instantiated. It specifies an interface of methods that derived classes must override in order to implement its functionality.
We start by importing the necessary packages, the awt package, the event package, and java.util.Hashtable.
The class is declared as a public, abstract class which derives from java.awt.Component.
import java.awt.*;
Import java.awt.event.*;
Import java.util.Hashtable;
public abstract class ImageButton extends Component
{
|
//Declare data members
//Insert "ImageButton data members"
|
Locate the ImageButton data members clipping in the ImageButton folder and drag it directly below the last line of code shown above. Your code should now look like this:
import java.awt.*;
Import java.awt.event.*;
Import java.util.Hashtable;
public abstract class ImageButton extends Component
{
//Declare data members
//Insert "ImageButton data members"
|
protected Hashtable imageHash;
protected Image image;
protected String imageName;
protected Boolean isMouseDown = false;
protected Boolean isMouseInside = false;
protected String actionCommand;
protected ActionListener actionListener = null;
|
We declare all of the data members as protected. This is because we do not want them to be accessible except by derived classes. The first data member is imageHash. We will use the hashtable to keep track of the button images. We chose to use a hashtable because we wanted to be able to store an arbitrary number of images and retrieve them by name. It is the responsibility of the derived class to swap images based on state or user interaction.
The second member, image, referrers to the currently displayed image. The variable imageName is a String representing the name of this image.
Next, we have some state information about the mouse. The members isMouseDown and isMouseInside allow us to keep track of where the mouse is located so that we can perform rollover actions correctly. These variables will primarily be used by the derived classes.
The final two members, actionCommand and actionListener, are used for responding to user interaction. We will examine this in more detail in
Step 3 and Step
10.
Back to top
The main function of a button is to respond to user interaction such as a mouse press. In order to respond correctly to the mouse, we need to write an inner class for handling mouse events.
Scroll down to the very bottom of the source file where it reads:
public void paint(Graphics g)
{
//Let the super class draw, then handle drawing the current image.
//Insert "ImageButton paint"
}
|
//Inner class for handing mouse events.
//Insert "ImageButton Mouse Handling"
|
Locate the ImageButton Mouse Handling clipping in the ImageButton folder and drag it directly below the last line of code shown above. Your code should now look like this:
public void paint(Graphics g)
{
//Let the super class draw, then handle drawing the current image.
//Insert "ImageButton paint"
}
//Inner class for handing mouse events.
//Insert "ImageButton Mouse Handling"
|
class Mouse extends MouseAdapter
{
public void mouseExited(MouseEvent event)
{
ImageButton_MouseExited(event);
}
public void mouseEntered(MouseEvent event)
{
ImageButton_MouseEntered(event);
}
public void mouseReleased(MouseEvent event)
{
ImageButton_MouseReleased(event);
}
public void mousePressed(MouseEvent event)
{
ImageButton_MousePressed(event);
}
}
protected void ImageButton_MousePressed(MouseEvent event)
{
isMouseDown = true;
handleMousePressed( );
}
protected void ImageButton_MouseReleased(MouseEvent event)
{
isMouseDown = false;
handleMouseRelease(isMouseInside);
}
protected void ImageButton_MouseEntered(MouseEvent event)
{
isMouseInside = true;
handleRollover(isMouseInside, isMouseDown);
}
protected void ImageButton_MouseExited(MouseEvent event)
{
isMouseInside = false;
handleRollover(isMouseInside, isMouseDown);
}
|
Wow! Thats a lot of code. Dont worry. It is pretty straightforward. Lets look at it in more manageable sections.
First we declare a subclass of MouseAdapter called Mouse.
class
Mouse extends MouseAdapter {
MouseAdapter, in the java.awt.event package, is an abstract class that is provided as a convenience for easily creating listeners. Here, we override the class and implement the methods we are interested in: mouseEntered, mouseExited, mousePressed, and mouseReleased. These methods will be called when a certain type of MouseEvent occurs. When the user moves the mouse over the ImageButton, the mouseEntered( ) routine will be called. When the user moves the mouse outside of the ImageButton, the mouseExited( ) routine will be called. Similarly, mousePressed( ) and mouseReleased( ) are called when the mouse button is pressed and when the mouse button is released, respectively.
public void mouseExited(MouseEvent event)
{
ImageButton_MouseExited(event);
}
Each of these methods is defined in a similar fashion. The event that is received is passed off to a subordinate function. This is done for convenience. It makes the secondary method easier to override since it is not located inside the inner class.
The ImageButton_MousePressed( ) method is very simple:
protected void ImageButton_MousePressed(MouseEvent event)
{
isMouseDown = true;
handleMousePressed( );
}
It sets the isMouseDown data member to true and calls handleMousePressed( ). Remember that handleMousePressed( ) is defined in this class as an
abstract method and is overridden in RolloverButton. Thus, when the mouse button is pressed, it calls the method in the RolloverButton that provides the implementation. As a result, we handle the event in our low-level class, but respond to the user in our derived class.
ImageButton_MouseReleased( ), ImageButton_MouseEntered( ), and ImageButton_MouseExited( ) are very similar. They pass state information to the derived class via the abstract methods that are defined in the derived class. ImageButton_MouseReleased( ) is an exception in that it calls handleMouseRelease( ), which is the only non-abstract mouse handling routine. We will look at this method in more detail in Step 4.
Now it is time to go back up to the top of the file and look at the constructor where we register our listener we just created.
Next page
|