A Flash Developer Resource Site

Results 1 to 11 of 11

Thread: OOP troubles: Delegate with Iteration

  1. #1
    Senior Member
    Join Date
    Feb 2005
    Posts
    237

    OOP troubles: Delegate with Iteration

    Hi there.

    I'm using iteration within a class method to attach a series of button instances from the library to mc in my fla. So far so good, but when I try to use Delegate to give them an onRelease handler, it only works on the last button. Here is the rellevent code:

    Code:
    	//CREATE BUTTONS FROM XML
    	public function attachButtons (buttonLabel:Array, totalButtons:Number, buttons:Number):Void {
    		
    		//SET ITEM VARS
    		numVisibleItems = buttons;
    		numOfItems = totalButtons;
    		
    		var thisLb:XmlListBox = this;
    		var i;
    		
    		//ITTERATE THROUGH ARRAY TO PLACE BUTTONS
    		for (i = 0; i < numOfItems; i++) {
    			buttonContainer_mc = listBoxContainer_mc.background_mc.attachMovie ("listBoxButton", "button" + i, listBoxContainer_mc.background_mc.getNextHighestDepth ());
    			buttonContainer_mc._y = buttonContainer_mc._height * i;
    			buttonContainer_mc.title_txt.text = [i + 1] + " " + buttonLabel[i];
    			buttonContainer_mc.onRelease = buttonContainer_mc.onReleaseOutside = Delegate.create(this, setButtons, i);
    			
    			buttonContainer_mc.thisSelected_mc._alpha = 0;
    				
    		}
    		
    		sizeMask ();
    	}
    	
    	function setButtons(i:Number):Void {
    		
    		buttonContainer_mc._alpha = 100;
    		trace("IDENT"+buttonContainer_mc.thisSelected_mc._alpha);
    		trace("I IS:"+ i);
    		//current_track_number = i;
    		//stopmusic();
    		//playmusic();
    		
    	}
    Thanks a lot.
    Last edited by arkum; 07-10-2006 at 05:03 PM.

  2. #2
    Senior Member Computer Dork's Avatar
    Join Date
    Mar 2001
    Location
    St. Louis
    Posts
    1,026
    Are you trying to add the hyperlink to the listBoxButtons?

    The reason it ends up paying attention to the last on(release) is because you essentially reassign the onRelease every single loop, and the last one is what finally takes.

    You need to set up the loop to effect each button instead of the main container clip.

    Something like this -

    code:

    for (i = 0; i < numOfItems; i++) {
    listBoxContainer_mc.background_mc.attachMovie ("listBoxButton", "button" + i, listBoxContainer_mc.background_mc.getNextHighestDe pth ());
    listBoxContainer_mc.background_mc["button" + i]._y = listBoxContainer_mc.background_mc["button" + i]._height * i;
    listBoxContainer_mc.background_mc["button" + i].title_txt.text = [i + 1] + " " + buttonLabel[i];
    listBoxContainer_mc.background_mc["button" + i].onRelease = listBoxContainer_mc.background_mc["button" + i].onReleaseOutside = Delegate.create(this, setButtons, i);

    listBoxContainer_mc.background_mc["button" + i].thisSelected_mc._alpha = 0;

    }



  3. #3
    Senior Member
    Join Date
    Feb 2005
    Posts
    237
    Hi there.

    Thanks for getting back to me. That all works great apart from getting the setButtons method to fire the bit of code in blue (I've just edited it) as there is no route back to the button and Delegate won't let me send i as a variable (it returns as undefined);

    Any ideas?

  4. #4
    Senior Member
    Join Date
    Feb 2005
    Posts
    237
    Bump

  5. #5
    Monkey Moderator Lexicon's Avatar
    Join Date
    Jul 2001
    Location
    UK
    Posts
    2,038
    mx.utils.Delegate class does not take into account any passed variables, there is no third argument in the create method of the class and so it will be ignored.

    Instead of delegating the scope of the button events to that of the class, you could just pass a reference to the scope of the class object and use that variable to access the class objects methods and properties from the scope of the buttons. That would probably be how most people would handle it.

    However, there is a trick you can do so you can write your own version of the Delegate class that will pass any number of arguments which might save you reworking what you already have...

    Code:
    class lexicon.utils.Delegate extends Object
    {
    	static function create(obj:Object, func:Function):Function
    	{
    		var f = function()
    		{
    			var target = arguments.callee.target;
    			var func = arguments.callee.func;
    			var args = arguments.callee.args;
    
    			return func.apply(target, arguments.concat(args));
    		};
    
    		f.target = obj;
    		f.func = func;
    		f.args = (arguments.length>2) ? arguments.slice(2) : [];
    		
    		return f;
    	}
    		
    	function Delegate(f:Function)
    	{
    		func = f;
    	}
    
    	private var func:Function;
    
    	function createDelegate(obj:Object):Function
    	{
    		return create(obj, func);
    	}
    }
    so you could assign the event functions to this if you wanted...
    Code:
    lexicon.utils.Delegate.create(this, setButtons, i, buttonContainer_mc);
    and access the passed vars in your setButtons function...
    Code:
    function setButtons(i:Number, mc:MovieClip):Void 
    {		
    	mc._alpha = 100;
    	trace("IDENT"+buttonContainer_mc.thisSelected_mc._alpha);
    	trace("I IS:"+ i);
    	//current_track_number = i;
    	//stopmusic();
    	//playmusic();		
    }
    www.lexicon-design.co.uk
    If we aren't supposed to eat animals, then why are they made of meat?
    If Vegetarians like animals so much, why do they eat all their food?

  6. #6
    Senior Member
    Join Date
    Feb 2005
    Posts
    237
    Thanks Lexicon. That is perfect.

    Instead of delegating the scope of the button events to that of the class, you could just pass a reference to the scope of the class object and use that variable to access the class objects methods and properties from the scope of the buttons. That would probably be how most people would handle it.
    I totally understand your "trick" solution, but just out of interest, if you have a couple of spare minutes, can you try to explain the quoted chunk to me. I've read it again and again, but it's not going in.

  7. #7
    Monkey Moderator Lexicon's Avatar
    Join Date
    Jul 2001
    Location
    UK
    Posts
    2,038
    I meant that you could do something like this, where the reference to the class object is passed to the button so that the function in the class object scope can be called from within the button scope.

    It's easier to explain in code ...

    Code:
    class MyMenu extends MovieClip
    {	
    	// declare the button specific vars so you don't get compile errors.
    	var scope:MovieClip, id:Number;
    	
    	// constructor
    	function MyMenu()
    	{
    		var _mc:MovieClip;
    		for(var i:Number=0; i<5; i++)
    		{
    			// create the clips and assign the mouse event
    			_mc = createEmptyMovieClip('_btn'+i, i);
    			_mc.onRelease = buttonRelease;
    			
    			// vars to be passed as argument to the someClassFunc
    			_mc.id = i;
    			// a reference to the class object so that the someClassFunc can be correctly addressed and executed
    			_mc.scope = this;
    			
    			// draw and position the buttons
    			_mc.beginFill(0xFF, 100);
    			_mc.lineTo(50,0);
    			_mc.lineTo(50,50);
    			_mc.lineTo(0,50);
    			_mc.lineTo(0,0);
    			_mc.endFill();
    			_mc._y = i*55;
    		}
    	}
    	
    	// function will run in the class object scope
    	private function someClassFunc(id:Number, btn:MovieClip):Void
    	{
    		trace("Button id: "+id);
    		trace("Button ref: "+btn);
    		trace("Scope of this function: "+this);
    	}
    	
    	// the onRelease function running in the individual button's scopes
    	private function buttonRelease(Void):Void
    	{
    		this.scope.someClassFunc(this.id, this);
    	}
    }
    www.lexicon-design.co.uk
    If we aren't supposed to eat animals, then why are they made of meat?
    If Vegetarians like animals so much, why do they eat all their food?

  8. #8
    Senior Member
    Join Date
    Feb 2005
    Posts
    237
    Thanks Lexicon. Much apreciated.

  9. #9
    Senior Member
    Join Date
    Feb 2005
    Posts
    237
    In the situation I am using it, instead of passing the argument on to the method, your class passes the path.

    If you have a quick look at the attached files you will see what I mean.

    The button.onRelease works fine, but the onLoadInit goes crazy.

    Am I missing something here?

    Thanks as always
    Attached Files Attached Files

  10. #10
    Monkey Moderator Lexicon's Avatar
    Join Date
    Jul 2001
    Location
    UK
    Posts
    2,038
    hi,

    you did not pass the container parameter in you Fla when adding the class object.

    you also forgot to add the parenthesis in this line...

    var imageLoader:MovieClipLoader = new MovieClipLoader();


    Lastly because the MovieClipLoader passes a parameter anyway (e.g. the target), the extra parameters you add with the delegate function will be appended.

    e.g.
    Code:
    private function output(answer:Number)
    {
    	trace("ANSWER "+answer +"    "+t)
    }
    will need to become...

    Code:
    private function output(target:MovieClip, answer:Number)
    {
    	trace("ANSWER "+answer)
    }
    so it's better not to use this method to assign the same function to a MovieClipLoader and a MovieClip.
    www.lexicon-design.co.uk
    If we aren't supposed to eat animals, then why are they made of meat?
    If Vegetarians like animals so much, why do they eat all their food?

  11. #11
    Senior Member
    Join Date
    Feb 2005
    Posts
    237
    Thanks (again) Lexicon. Everything is now sorted out. I O U.

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