use action-listeners on userdefined objects in a canvas

I have a canvas containing objects ( which are ludo game
pieces here). For drawing these objects on the screen, they
contain x and y coordinates relative to the convas. What I need is actionListeners on every object, so that its not needed to verify the position of a mouse click, but directly  
jump to the actionPerformed method.

This easily done for buttons, menuItems and such but how do I make one for a component?
LVL 3
moonlightAsked:
Who is Participating?
 
mjenkinsCommented:
You need to derive your Object from Component, of course. Once that is done, make sure the objects implements

addActionListener()
removeActionListener()
protected void processEvent(AWTEvent e)
protected void processActionEvent(ActionEvent e)

0
 
evijayCommented:
are these objects extend from Component ?

If so, you can make these objects implement MouseListener and then in the mouseClicked method of it, fire a actionEvent.
You need to add the methods addActionListener and removeActionListener to these objects and maintain listeners in a vector. In the mouse click event, you need to invoke a fireActionEvent method (which you implement). In the fireActionEvent method, you create a ActionEvent, traverse thru the listener vector and invoke the actionPerformed method for each element in vector.

vijay

0
 
mjenkinsCommented:
Here is a complete example just to make it easier to understand:

import java.awt.*;
import java.awt.event.*;
 
public class Act
        extends Canvas
{
    private ActionListener actionListener;
 
        public static void main( String args[] )
        {
                Frame f = new Frame( "Act" );
                f.setSize( 400,400 );
                Act a = new Act( );
                f.add( a );
                a.addActionListener( new ActionListener()
                        {
                                public void actionPerformed( ActionEvent e )
                                {
                                        System.out.println( "DONE" );
                                }
                        }
                );
                f.setVisible(true);
        }
 
        public Act()
        {
                setSize( 100,100 );
                enableEvents( AWTEvent.MOUSE_EVENT_MASK | AWTEvent.ACTION_EVENT_MASK );
        }
 
    public synchronized void addActionListener(ActionListener l)
        {
                actionListener = AWTEventMulticaster.add(actionListener, l);
    }
 
    public synchronized void removeActionListener(ActionListener l)
        {
                actionListener = AWTEventMulticaster.remove(actionListener, l);
    }
 
    protected void processEvent(AWTEvent e)
        {
        if (e instanceof MouseEvent)
                {
                        if( e.getID() == MouseEvent.MOUSE_RELEASED )
                processActionEvent( new ActionEvent(e.getSource(),ActionEvent.ACTION_PERFORMED, "ACTION!") );    
        }
                super.processEvent(e);
    }
 
    protected void processActionEvent(ActionEvent e)
        {
        if (actionListener != null)
                {
            actionListener.actionPerformed(e);
        }
    }
}

Notice that it is our responsibilty to convert the MouseEvent into an ActionEvent. I hope this puts the matter in perspective.
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
moonlightAuthor Commented:
Hi,
I've tested your sample code, but it doesnt respond the way I want it to. It doesnt matter where you click and I want it to. Isn't it what you should achieve with setSize(100,100) in Act () ?

How do I make an invisible area on the screen which will generate the object's actionPerformed() and send the object to it, when clicked on? as opposed to what I see now when it runs actionPerformed() on all clicks everywhere?
0
 
mjenkinsCommented:
The reason that it responds no matter where you click, is that the layout manager is resizing the component (even though I set it to 100,100). The default layout for Frame is BorderLayout. BorderLayout expands the "Center" component to the size of the container. If you insert:

f.setLayout( null );

right after

f.setSize(400,400);

You will see the behavior you are expecting. The app will print "DONE" only while clicking in the area bounded by 0,0,100,100.

You need to manage the size of your components in your actual application.
0
 
mjenkinsCommented:
Well, did it work? Are you satisfied with your answer?
0
 
moonlightAuthor Commented:
thank you for the help. sorry for dealy.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.