A Flash Developer Resource Site

Page 1 of 2 12 LastLast
Results 1 to 20 of 28

Thread: Passing args with event ?

  1. #1
    Junior Member
    Join Date
    Mar 2003
    Location
    Quebec !
    Posts
    9

    Passing args with event ?

    Hi,

    I'm a professional flash game developer and my week planning is to learn AS3 (kinda...cool )

    I've just started something but there is one minor problem.... I can't find a way to pass args with eventListener

    back in the day (...like last week) in AS2 I used something like this :

    Code:
    myBtn.onRelease = Delegate.create(this, someFunc, someArgs)
    Let's say I was using a custom Delegate with args...

    but now with AS3 I need to do this


    Code:
    myBtn.addEventListener(Event.CLICK, someHandlerFunc)
    
    function someHandlerFunc(){
           someFunc(someArgs)
    }
    It's still work well... but it's kinda a pain to write an handler function for each btn (or whatever event sending object) I need. I mean.. if I have something like

    Code:
    function addPage(_nPage){
           nPage += _nPage
    }
    and I got 3 button with "+1", "+2" and "+3" ... I'll do something like this ?

    Code:
    btn1.addEventListener(Event.CLICK, btn1Handler)
    btn2.addEventListener(Event.CLICK, btn2Handler)
    btn3.addEventListener(Event.CLICK, btn3Handler)
    
    function btn1Handler(){
          addPage(1);
    }
    
    function btn2Handler(){
          addPage(2);
    }
    
    function btn3Handler(){
          addPage(3);
    }

    is it me or it's kinda "ugly" ? I mean.. I could write 3 onRelease with Delegate in AS2... now I need 3 addEventListener with 3 function...

    Thanks !
    OULALALALLALAOUAOUALALLALL...

    I hate signature

  2. #2
    Member
    Join Date
    Mar 2007
    Posts
    33
    You don't need 3 functions, you can check the event target which will be the clicked button and then act accordingly.

  3. #3
    Senior Member cancerinform's Avatar
    Join Date
    Mar 2002
    Location
    press the picture...
    Posts
    13,449
    Here is something you can do as example but only with MovieClips:
    PHP Code:
    var but1:MovieClip = new MyButton();
    var 
    but2:MovieClip = new MyButton();
    var 
    but3:MovieClip = new MyButton();
    but2.x=150;
    but3.x=300;
    this.addChild(but1);
    this.addChild(but2);
    this.addChild(but3);
    but1.addEventListener(MouseEvent.CLICKbutfunc);
    but2.addEventListener(MouseEvent.CLICKbutfunc);
    but3.addEventListener(MouseEvent.CLICKbutfunc);
    but1.mc "1";
    but2.mc "2";
    but3.mc "3";
    function 
    addPage(arg:String)
    {
        
    trace(arg);
    }
    function 
    butfunc(e:Event)
    {
        
    addPage(String(e.target.mc));

    and the class for the MyButton:
    PHP Code:
    package 
    {
        
    import flash.display.MovieClip;
        public class 
    MyButton extends MovieClip
        
    {
            public var 
    mc:String;
            public function 
    MyButton()
            {
            }
        }

    - The right of the People to create Flash movies shall not be infringed. -

  4. #4
    half as fun, double the price senocular's Avatar
    Join Date
    Feb 2002
    Location
    San Francisco, CA (USA)
    Posts
    4,361
    You could also make your own delegate-esque wrapper for adding arguments
    Code:
    function addArguments(method:Function, additionalArguments:Array):Function {
    	return function(event:Event):void {
    		method.apply(null, [event].concat(additionalArguments));
    	}
    }
    
    stage.addEventListener("click", addArguments(handleClick, [1,2,3]));
    function handleClick(event:Event, a:int, b:int, c:int):void {
    	trace(arguments); // [MouseEvent ...], 1, 2, 3
    }

  5. #5
    Junior Member
    Join Date
    Mar 2003
    Location
    Quebec !
    Posts
    9
    Quote Originally Posted by senocular
    You could also make your own delegate-esque wrapper for adding arguments
    Code:
    function addArguments(method:Function, additionalArguments:Array):Function {
    	return function(event:Event):void {
    		method.apply(null, [event].concat(additionalArguments));
    	}
    }
    
    stage.addEventListener("click", addArguments(handleClick, [1,2,3]));
    function handleClick(event:Event, a:int, b:int, c:int):void {
    	trace(arguments); // [MouseEvent ...], 1, 2, 3
    }

    ...that ...is nice

    I'll try each solution and see which one suit the best for our team (...about 20 coder :S)
    OULALALALLALAOUAOUALALLALL...

    I hate signature

  6. #6
    Junior Member
    Join Date
    Mar 2003
    Location
    Quebec !
    Posts
    9
    Hey !

    Based on your little code I've created a (realy simple) class which act like the old "arguments supported delegate"..without changing the scope

    Code:
    package {
    	
    	import flash.events.Event;
    	
    	public class CallArg{
             
             
            public function CallArg(){
    		
            }
             
    	public static function create(method:Function, ... args):Function {
    		return function(event:Event):void{				
    			method.apply(null, [event].concat(args));
    		}		
    	}
         }
    
    }
    Use :

    Code:
     someObj.addEventListener(SOME_EVENT, CallArg.create(SOME_FUNC, ARG1, ARG2, ARG3 ) )
    and the listening handler should have his first arguments as an Event

    Code:
    SOME_FUNC(_event:Event, ARG1, ARG2, ARG3) { 
    
    }
    Attached Files Attached Files
    OULALALALLALAOUAOUALALLALL...

    I hate signature

  7. #7
    Member
    Join Date
    Feb 2007
    Location
    Sydney, Australia
    Posts
    44
    Nice little workaround with the class, but how would you remove the eventListener when you're done?

    I can't seem to get rid of it!

  8. #8
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136
    I haven't tried the above class script, but looking at it I'd guess there are going to be some scope problems and some serious memory leaks over time...because the functions you're creating are going to be...I think...scoped to the CallArg class. They'll never get collected as garbage as long as an instance of that class is open, and you won't be able to get rid of the listeners. You'd need to weak-link your eventListeners and instantiate the WHOLE CLASS each time you wanted to create one event...not use the same class over and over to create multiple functions. Maybe I'm talking out my a**, but that's what it looks like to me.

  9. #9
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136
    Y'know what might be a nicer way, actually...well, depends what you want, but it's a little like the old AS2 method...

    Make a dynamic class that extends Sprite, and use it for all your sprites. They you can assign whatever properties you want to that sprite, and pick them up when the event comes through... like

    Code:
    var z:DynamicSprite = new DynamicSprite();
    z.args = new Array("some","stuff");
    z.addEventListener(MouseEvent.ROLL_OVER,this.overFunction);
    function overFunction(evt:MouseEvent) {
          trace (evt.target.args[0]+evt.target.args[1]); //should read "somestuff"
    }
    Obviously, you could also just take advantage of MovieClips, but I'd think a dynamic sprite class would still be a lot faster. This would be the equivalent of the AS2 code:

    [CODE]
    someMC.args = new Array("some","stuff");
    someMC.onRollOver = function() {
    trace (this.args[0]+this.args[1]);
    }

  10. #10
    Member
    Join Date
    May 2007
    Location
    Poland
    Posts
    65
    There's yet one more way to do what you want and I guess it is most clean OOP one. You can create a class that extends the Event class, adding your own arguments straight to the event, so they are sent together with the event... 'cos that's what you're looking for, am I right?

    I made myself an event class that informs that a property of animated object changed and it sends the changed value together with the event. I gave it a name AnimEvent (and it is actually working in one of the apps I create right now):

    PHP Code:
    package {
        
    import flash.events.Event;
        
        public class 
    AnimEvent extends Event {
            public static const 
    ALPHA_CHANGE:String "alpha_change";
            public static const 
    X_CHANGE:String "x_change";
            public static const 
    Y_CHANGE:String "y_change";
            public static const 
    SCALE_X_CHANGE:String "scale_x_change";
            public static const 
    SCALE_Y_CHANGE:String "scale_y_change";
            
            public var 
    value:Number;
            
            public function 
    AnimEvent(type:Stringvalue:Number)
            {
                
    super(type);
                
    this.value value;
            }
            
            public 
    override function clone():Event
            
    {
                return new 
    AnimEvent(typevalue);
            }
            
            public 
    override function toString():String
            
    {
                return 
    formatToString("AnimEvent""type""value""bubbles""cancelable""eventPhase");
            }
        }

    Then if you want to dispatch the event from inside the animated object, you go like that (let's say for alpha change):

    PHP Code:
    import AnimEvent;
    var 
    alphaEvent:AnimEvent=new AnimEvent(AnimEvent.ALPHA_CHANGEvalue);
    dispatchEvent(alphaEvent); 
    And the listener registering is just standard AS3 way:

    PHP Code:
    import AnimEvent;
    function 
    myListener(event:AnimEvent){ 
       
    trace("alpha: ",event.value);
    }
    var 
    myAnim:MyAnim=new MyAnim(); //some animation object that dispatches the event
    myAnim.addEventListener(AnimEvent.ALPHA_CHANGEmyListener); 
    This way you can dispatch an event that you define yourself (you can use one of the static consts of the class to say what type of event it is) and you can send a value (or more values, if you need) with it.

    Please say if it is what you were looking for
    Last edited by ampo_webdesign; 05-31-2007 at 02:39 PM.

  11. #11
    Member
    Join Date
    Feb 2007
    Location
    Sydney, Australia
    Posts
    44
    ampo_webdesign, if it's working in your code, then what you've described is what I want!

    But being that I'm learning AS3 right now, I just need to research some of what's going on in your code, since I'm not familiar with some of the terms, such as super(), the clone() thing, why I see no call to these "override" functions and such....

    But I'm sure that's outside the scope of this thread....

    Thanks regardless!

  12. #12
    Member
    Join Date
    May 2007
    Location
    Poland
    Posts
    65
    Yes, it is working, and as you put the class definition in a separate .as file and you forget about its existence, this way is actually very comfy. It simply adds to the standard syntax of AS3 events - so it is a seamless extension to the language. You just gain another event class, and use it like the standard Event class, MouseEvent class and all the other event classes

    Here are some short answers to your follow-up questions:

    1. All I do in this class is extending another class - Event (that is ready made in AS3). Extending is like saying: "my class is just like that class, only mine has some little things more..."

    2. The super() is a method of invoking the original class that I'm about to extend - in the OOP language you name the one a 'superclass'. You can think of the super() method as creating the original class inside the new one. In this case we invoke the original Event class (it's constructor) and from that moment our new class has all the properties and methods of the Event class, so we don't need to build it from scratch. Actually the super() method would be called in my constructor (which is the AnimEvent function) even if I didn't put it there. But because I explains a lot, I call it explicitly.

    3. The clone() is just a method of the Event class. Every time you define a new event class based on Event class, two methods have to be redefined: clone() and toString(). (I know it from the book .) So the clone() is just a function (or method) that I redefine.

    4. The override syntax is just telling that you redefine a method. We are given a clone() method from Event class, but we don't want that one, because we build ourselves a new one, so we override the original with our version.

    I hope this'll give you an easy start
    Last edited by ampo_webdesign; 06-01-2007 at 02:20 AM.

  13. #13
    will i ever get it?
    Join Date
    Feb 2004
    Posts
    707
    Quote Originally Posted by ampo_webdesign
    I made myself an event class that informs that a property of animated object changed and it sends the changed value together with the event. I gave it a name AnimEvent (and it is actually working in one of the apps I create right now):

    PHP Code:
    package {
        
    import flash.events.Event;
        
        public class 
    AnimEvent extends Event {
            public static const 
    ALPHA_CHANGE:String "alpha_change";
            public static const 
    X_CHANGE:String "x_change";
            public static const 
    Y_CHANGE:String "y_change";
            public static const 
    SCALE_X_CHANGE:String "scale_x_change";
            public static const 
    SCALE_Y_CHANGE:String "scale_y_change";
            
            public var 
    value:Number;
            
            public function 
    AnimEvent(type:Stringvalue:Number)
            {
                
    super(type);
                
    this.value value;
            }
            
            public 
    override function clone():Event
            
    {
                return new 
    AnimEvent(typevalue);
            }
            
            public 
    override function toString():String
            
    {
                return 
    formatToString("AnimEvent""type""value""bubbles""cancelable""eventPhase");
            }
        }

    ampo_- i was thinking about this today...what if the desired returned property is not something that is a number? For example, the above event will always return a value that is a number, but what if the dispatch was sometimes a string? Do you have to write a different event extension to make this possible?

  14. #14
    Member
    Join Date
    May 2007
    Location
    Poland
    Posts
    65
    Quote Originally Posted by mlecho
    ampo_- i was thinking about this today...what if the desired returned property is not something that is a number? For example, the above event will always return a value that is a number, but what if the dispatch was sometimes a string? Do you have to write a different event extension to make this possible?
    Yes, you have to write different event extension in that case. One of the ideas behind AS3 is strict typing of variables, properties and values. This strict typing makes the code safer and easier to debug (if you make a mistake with an assignment, the compiler can easier find and report it). So this approach is consistent with AS3 more-mature-programming ideology.

    Please notice that the class I gave as an example is an event class that reports a change in an animated object's property - which is always a numer. So it is obvious that the value property of my event is of Number type.

    If you need badly to override the typing, I guess you could use the * special type (or better said - no type), like that:
    Code:
    var value:*;
    I've never tested it though, because it wouldn't be that AS3-consistent, would it? I consider the strict typing one of the advantages of AS3 and I'm after taking advantage of this advantage

  15. #15
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136
    no-typing is nice when passing compound objects back and forth to a server, though

  16. #16
    Senior Member
    Join Date
    Aug 2002
    Location
    Dublin, Ireland
    Posts
    1,749
    New to AS 3.0 myself, but it occurs to me you could get around the typing issue by having ...(rest) syntax in the constructor for your new AnimEvent and updating the additional argument storage code accordingly.
    G

  17. #17
    Member
    Join Date
    May 2007
    Location
    Poland
    Posts
    65
    Quote Originally Posted by AlsoGaiusCoffey
    New to AS 3.0 myself, but it occurs to me you could get around the typing issue by having ...(rest) syntax in the constructor for your new AnimEvent and updating the additional argument storage code accordingly.
    G
    I do not consider the typing an issue, I consider it an advantage. The beauty of AS3 is that everything is so strict and clean - I have an object which is prepared strictly for what I need in a specific field, and not for everything I could need on every field. Afterall, this is what objects are about, also in real life - if I have a bicycle, I cannot use it for slicing bread.
    Thanks to strict typing my beloved compiler can help me find all my mistakes, it saves my time and frustration. Why would I want to break it or make it's work harder?

  18. #18
    Senior Member
    Join Date
    Aug 2002
    Location
    Dublin, Ireland
    Posts
    1,749
    Easy tiger, I'm happy to OOP and in basic agreement with you.

    My post is just an approach to get around something that _is_ occasionally required - especially for testing concepts. Sometimes, you just want throwaway code to see if something will work.

    It's the same with database design where normalisation is a brilliant and very powerful concept that only an idiot would ignore. But, go too far and even the simplest update becomes a string of fifty or more SQL statements.

    Life is a compromise.

  19. #19
    Member
    Join Date
    May 2007
    Location
    Poland
    Posts
    65
    Quote Originally Posted by AlsoGaiusCoffey
    Easy tiger, I'm happy to OOP and in basic agreement with you.
    Life is a compromise.
    i didn't want to fight either sorry if I sounded too harsh

  20. #20
    Senior Member
    Join Date
    Aug 2002
    Location
    Dublin, Ireland
    Posts
    1,749
    No worries, all good.
    BTW, as an aside, there is a legitimate OOP example where ...(rest) is not only a workaround, but also the only way to achieve it in Flash (as far as I know - I'm happy to be educated).
    Supposing you have multiple argument lists that you want to use for the same function. EG: A calculation that can either take [Point(),width,height], [x1,y1,x2,y2] or [MyShape()] as arguments but always does basically the same calculation.
    You _could_ have multiple different functions ("myFuncXYWH()", "myFuncMyShape()", "myFuncPWH()") but imagine how unreadable and unmaintainable your code would then be (see also http://www.thc.org/root/phun/unmaintain.html for a laugh).
    In Java (or similar), you can overload the function definitions with different argument signatures, but in AS3.0, there is no way to achieve this without ...(rest).
    code:

    private function myFunc(...(args)):Object {
    var xin:Number;
    var yin:Number;
    var w:Number;
    var h:Number;
    if(args[0] is Point)) {
    // assign vars
    } else if(args[0] is MyShape)) {
    // assign vars
    } else {
    // assign vars
    }
    return {tlc:new Point(xin,yin), brc:new Point(xin+w,yin+h), area:w*h};
    }


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center