We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

use action-listeners on userdefined objects in a canvas

moonlight
moonlight asked
on
Medium Priority
355 Views
Last Modified: 2008-03-03
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?
Comment
Watch Question

Commented:
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

Commented:
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview

Commented:
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.
moonlightSenior Technology Consultant
CERTIFIED EXPERT

Author

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?

Commented:
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.

Commented:
Well, did it work? Are you satisfied with your answer?
moonlightSenior Technology Consultant
CERTIFIED EXPERT

Author

Commented:
thank you for the help. sorry for dealy.
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.