A Flash Developer Resource Site

Results 1 to 12 of 12

Thread: parent problem

  1. #1
    Senior Member
    Join Date
    Apr 2001
    Posts
    996

    parent problem

    I have a movieClip on the stage at runtime. Its instance name is menuHolder. I add a sprite to this movieClip and inside the sprite I did a trace for the parent and it showed up as null?

    I have a document class that loads some xml like so.
    Code:
    package com{
    	
    	import flash.display.Sprite;
    	import flash.events.*;
    	import com.menu.NavigationBar;
    	import com.xml.LoadXml;
    	
    	public class Main extends Sprite{
    		
    		private var _navBar : NavigationBar;
    		private var _appData : LoadXml;
    		
    		public function Main() {
    			_appData = new LoadXml('../deploy/menu.xml');
    			_appData.addEventListener('xmlLoaded', onLoadXML, false, 0, true );
    			
    		}
    		
    		private function onLoadXML( evt : Event ) : void {
    			_navBar = new NavigationBar(this, _appData.xmlData );
    			menuHolder.addChild(_navBar);
    			
    		}
    	}
    	
    }
    My NavigationBar class looks like this.

    Code:
    package com.menu{
    	
    	import flash.display.Sprite;
    	
    	public class NavigationBar extends Sprite{
    		
    		private var _main : Sprite;
    		private var _navData : XMLList;
    		
    		public function NavigationBar( main : Sprite, navData: XML) {
    			_main = main;
    			this.name = 'menu_container';
    			_navData = navData.member;
    			build();
    			
    		}
    		
    		private function build() : void {
    			trace(" parent = "+this.parent);
    			
    			for( var i : uint; i < _navData.length(); i++ ){
    				
    			}
    			
    		}
    	}
    }
    As you can see I'm trying to do a trace to see that my parent is actually the
    menuHolder movieclip on the main stage.
    The trace shows as
    parent = null
    Why would parent be null when the sprite has been added to the menuHolder display list? Or am I thinking this wrong.

    Thanks

  2. #2
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    You are thinking wrong. The trace is called within build, which is called by the constructor. This all happens before the addChild happens, which means that it's not on the parent's displaylist yet, and therefore it doesn't have a parent.

    The good news is that right after that it DOES get added to the parent and the trace would work as expected at that time.

  3. #3
    Senior Member
    Join Date
    Apr 2001
    Posts
    996
    Ah thanks for the tip.
    I added an event to trace it like this.
    Code:
    this.addEventListener(Event.ADDED_TO_STAGE, traceParent, false, 0, true );
    then in the traceParent function I did the same trace and it showed the parent. Ok one question down an here is another.


    As a matter of interest I could easily not make this class a sprite and just send in a reference to the movieclip on the stage. This would work better becaue there is no need to create an extra sprite to live inside the already created menuHolder on the stage.

    When I tried to cast the menuHolder as a MovieClip it threw another error.
    1046: Type was not found or was not a compile-time constant: MovieClip.
    Does anyone know why I can't use the strict data type as MovieClip

  4. #4
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    You probably just need to
    Code:
    import flash.display.MovieClip;
    in NavigationBar.as to resolve that error.

    If your NavigationBar has no visual appearance of its own, then I would suggest not making it a Sprite. But that seems a fairly odd design. I would expect a NavigationBar to be a DisplayObject. I think you mean that it would create other DisplayObjects and attach them to a parent. Which is fine. I'd change the name though, to make it NavigationUtil or something, and probably make the methods static rather than instantiate it.

  5. #5
    Senior Member
    Join Date
    Apr 2001
    Posts
    996
    Ok never mind stupid of me I forgot to import the MovieClip class.
    import flash.display.MovieClip;

    Thanks for the help the change over to AS3 is kicking my ass

  6. #6
    Senior Member
    Join Date
    Apr 2001
    Posts
    996
    I have everything working now except I wanted to dispatch a custom event to other classes that could listen for this event.

    my custom Event is

    Code:
    package com.menu{
    	
    	import flash.events.Event;
    	
    	public class MenuClickEvent extends Event {
    		
    		public static const MENU_CLICK:String = "menuClick";
    		public var arg:*;
    		
    		public function MenuClickEvent(type:String, customArg:*=null, bubbles:Boolean=false, cancelable:Boolean=false) {
    			super(type, bubbles,cancelable)
    			this.arg = customArg;
    	}
    	
    	public override function clone():Event {
    		return new MenuClickEvent(type, arg, bubbles, cancelable);
    	}
    	
    
    	public override function toString():String {
             return formatToString("MenuClickEvent", "type", "arg");
          }
    	
    }
    	
    }
    Then in my document class I instantiate another class called PageOpener
    Code:
    package com{
    	
    	import flash.display.Sprite;
    	import flash.events.*;
    	import com.menu.Navigation;
    	import com.xml.LoadXml;
    	import com.menu.PageOpener;
    	
    	public class Main extends Sprite{
    		
    		private var _navBar : Navigation;
    		private var _appData : LoadXml;
    		private var _pageOpener : PageOpener;
    		
    		public function Main() {
    			_appData = new LoadXml('../deploy/menu.xml');
    			_appData.addEventListener('xmlLoaded', onLoadXML, false, 0, true );
    			
    		}
    		
    		private function onLoadXML( evt : Event ) : void {
    
    			_navBar = new Navigation(this, _appData.xmlData, menuHolder );
    			_pageOpener = new PageOpener();
    
    			
    		}
    	}
    	
    }
    The PageOpener class looks like this.

    Code:
    package com.menu {
    	
    	import flash.events.*;
    	import com.menu.MenuClickEvent;
    	
    	public class PageOpener {
    		
    		public function PageOpener(){
    			setUpAssets();
    		}
    		
    		private function setUpAssets() : void {
    			addEventListener(MenuClickEvent.MENU_CLICK, onOpen, false, 0, true );
    		}
    		
    		private function onOpen(evt : MenuClickEvent) : void {
    			trace("MENU TO OPEN");
    		}
    		
    	}
    }
    The problem is I'm trying to get PageOpener class to be able to listen for the custom Event that is been dispatched from another class.
    When I publish my movie I get an error.

    [QUOTE]1180: Call to a possibly undefined method addEventListener.

  7. #7
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    This is a common point of misunderstanding. Events are not global. You must call addEventListener on the dispatcher you are interested in. You could do this:
    Code:
    _navBar.addEventListener(_pageOpener.onOpen);
    You will have to make onOpen public to do that.
    Last edited by 5TonsOfFlax; 01-09-2009 at 11:56 PM.

  8. #8
    Senior Member
    Join Date
    Apr 2001
    Posts
    996
    I'm completely confused. So what would be the point of a customEvent dispatcher if other objects can't listen.

    So how would I call the open function Directly from my other class. Would I have to pass a reference to the PageOpener object into the other class to call a method of the PageOpener class. This just doesn't seem like good OOP practice.

  9. #9
    Senior Member
    Join Date
    Apr 2001
    Posts
    996
    The class I'm trying to dispatch from is
    Code:
    package com.menu {
    	
    	import flash.display.Sprite;
    	import com.menu.Navigation;
    	import flash.text.TextField;
    	import flash.events.*;
    	import com.menu.MenuClickEvent;
    	
    	public class MenuButton extends Sprite {
    		
    		private var _handler : Navigation;
    		private var _strTitle : String;
    		public var _label : TextField;
    		private var _id : Number;
    		
    		public function MenuButton(handler : Navigation, strTitle : String, ID : Number ) { 
    			_handler = handler;
    			_strTitle = strTitle;
    			_id = ID;
    			this.buttonMode = true;
    			addTitle();
    			addEventListener(Event.ADDED_TO_STAGE, onAdded, false, 0, true);
    		}
    		
    		private function addTitle() : void {
    			_label.text = _strTitle;
    			_label.mouseEnabled = false;
    		}
    		
    		private function onAdded(evt : Event ) : void {
    			removeEventListener(Event.ADDED_TO_STAGE, onAdded);
    			addEventListener(MouseEvent.MOUSE_UP, onClick, false, 0 ,true );
    		}
    		
    		private function onClick( evt : MouseEvent ) : void {
    			dispatchEvent(new MenuClickEvent(MenuClickEvent.MENU_CLICK, 'hello'  ));
    		}
    		
    		
    	}
    	
    }
    If another class cant listen for this event then how could I call the onOpen method in the class pageOpener. I tried to send a reference to the document class all the way to this MenuButton class which was kind of ugly way of doing it but that didn't work it threw an error.
    I created a public function in the document class that when called would call the method onOpenPage()
    Code:
    		
    public function onOpenPage() : void {
    			_pageOpener.onOpen();
    		}
    [QUOTE]1061: Call to a possibly undefined method onOpenPage through a reference with static type flash.display:Sprite.

  10. #10
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    What I'd do is instead of dispatching directly from MenuButton, dispatch from the Navigation.

    in MenuButton.as:
    Code:
    		private function onClick( evt : MouseEvent ) : void {
    			_handler.dispatchEvent(new MenuClickEvent(MenuClickEvent.MENU_CLICK, 'hello'  ));
    		}
    In Main
    Code:
    		private function onLoadXML( evt : Event ) : void {
    
    			_navBar = new Navigation(this, _appData.xmlData, menuHolder );
    			_pageOpener = new PageOpener();
                            _navBar.addEventListener(MenuClickEvent.MENU_CLICK, _pageOpener.onOpen, false, 0, true);
    
    			
    		}
    You will want to make onOpen public, and remove the addEventListener statement in the constructor.

  11. #11
    Senior Member
    Join Date
    Apr 2001
    Posts
    996
    I tried what you suggested but got an error when I tried to call a method in the Main class.

    Code:
    		
    private function onLoadXML( evt : Event ) : void {
    	_pageOpener = new PageOpener();
    	_navBar = new Navigation(this, _appData.xmlData, menuHolder );
    	_navBar.addEventListener(MenuClickEvent.MENU_CLICK, onCallBack, true, 0, true);
    			
    		}
    		
    private function onCallBack(evt : MenuClickEvent ) : void {
    	trace("EVNT = "+evt.arg);
    _pageOpener.onOpen(evt.arg);
    	}
    Error
    [QUOTE]1061: Call to a possibly undefined method addEventListener through a reference with static type com.menu:Navigation.

  12. #12
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Sorry, I was forgetting that you changed Navigation to no longer extend Sprite. Now you want it to extend EventDispatcher.

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