EarthWeb
Developer.com
Site
windows 2000
visual c++
java
visual basic
javascripts
recommend it
 
Book
thinking in java
 
Interact
forum
guest book
jobs
jokes
what's new

share code
 
Resource
add resource
modify resource
new resource
 

[Internet Jobs]
-----
Java by E-mail:

Get the weekly e-mail highlights on Java!
-----

-

Dispatch Listener


Author: Bogdan Matasaru

An interesting aspect of the mechanism of dispatch maps from MFC is that the programmer doesn't care anymore about interpreting the parameters of an incoming message and calling the appropriate method. Still, there are the ugly macros BEGIN_MESSAGE_MAP, END_MESSAGE_MAP and the ON_xxx, but they are handled by the ClassWizard, so they are not very annoying. Actually, these maps are relations between events that may occur and the methods to be called in response.

Java allows a nicer approach due to the reflection mechanism. One can dynamically inspect an object for finding and calling a method of it.

For example, in a dialog one may find useful to attach to every button an action listener that responds to a click by searching a method of the dialog with the name obtained from the caption of the button and calling that method. More generally, the method must belong to a target object passed at the creation of the listener. There are cases where more buttons in a dialog or items from a menu have the same label. In this case one can use the pair of methods putClientProperty/ getClientProperty of the class JComponent to store/retrieve the name of the method to be called.

The example demonstrates this by implementing an ActionListener and using it with several sources of action events.

Here is the code of the actionPerformed method.


public void actionPerformed (ActionEvent e)
{
	if (target == null)
		return;

	// Obtain the name of the method from the action command.
	String methodName = toMethodName (e.getActionCommand ());

	// If the source is a JComponent, look for the property "MethodName".
	if (e.getSource () instanceof JComponent)
	{
		JComponent source = (JComponent)e.getSource ();
		Object prop = source.getClientProperty ("MethodName");
		if (prop != null)
			methodName = (String)prop;
	}

	if (methodName != null)
	{
		try
		{
			// The prototype of the method is void methodName (ActionEvent e)
			Class[] paramTypes = {Class.forName ("java.awt.event.ActionEvent")};
			Object[] paramValues = {e};

			// Obtain the method and invoke it.
			Method method = target.getClass ().getDeclaredMethod (methodName, paramTypes);
			method.invoke (target, paramValues);
		}
		catch (NoSuchMethodError noSuchMethodError)
		{
			System.err.println ("Method: void " + methodName + " (ActionEvent e) not found");
			return;
		}
		catch (Exception exc)
		{
			exc.printStackTrace ();
			return;
		}
	}
}

I think the comments are explanatory. The prototype of the method to be called is
void method (ActionEvent e).
The ActionEvent can be broken into components and passed in this way by changing the prototype of the method (see the paramTypes variable that represents the types of the parameters).

There are several ways to use it:

  • Create one listener for a target. In the example this is done b
    
    	this.listener = new ActionDispatchListener (this);
    
  • The label of the method is enough. In this case just add a method with the name as obtained from the toMethodName into the target object and add the listener to the list of action listeners the source. In the example this is used in the File|Exit menu item.
    
    	mi = (JMenuItem)file.add (new JMenuItem ("Exit", 'X'));
    	mi.addActionListener (listener);
    
  • Call putClientProperty ("MethodName", <method name>) for the event source, add the method with the specified name and add the listener to the list of listeners. In the example this is used for the button in the JInternalFrame derived class.
    
    	JButton button = new JButton ("Click Me");
    	button.putClientProperty ("MethodName", "onClickMe");
    	button.addActionListener (sample.listener);
    
  • If you plan to use this in many cases, for example for creating the items of a menu, one can derive a class and passing the name of the method to the constructor. In the example this is done by the JMethodMenuItem class.

Of course, the mechanism can be applied for other types of listeners. One such dispatch listener might implement several listener interfaces in this way.

Source Code

Posted On: 8-Mar-1999

internet.commerce



Acceptable Use Policy

internet.comMediabistrojusttechjobs.comGraphics.com

WebMediaBrands Corporate Info


Advertise | Newsletters | Feedback | Submit News

Legal Notices | Licensing | Permissions | Privacy Policy