dcsimg
A Flash Developer Resource Site

Results 1 to 5 of 5

Thread: [RESOLVED] Essential ActionScript 3 error #1009

Hybrid View

  1. #1
    Junior Member
    Join Date
    Feb 2009
    Posts
    3

    resolved [RESOLVED] Essential ActionScript 3 error #1009

    Hi all,
    I'm trying to follow the Essential ActionScript 3.0 book and I've hit a snag in chapter 22 at the CustomMousePointerDemo class. I'm using CS4 to compile with a CustomMousePointerDemo as the document class. I get this:

    TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at StageDetector/registerListeners()
    at StageDetector/setWatchedRoot()
    at StageDetector/setWatchedObject()
    at StageDetector()
    at CustomMousePointer()
    at CustomMousePointerDemo()


    when I try to test the movie.

    here is the CustomMousePointerDemo
    Code:
    // File CustomMousePointerDemo.as
    
    package {
    	import flash.display.*;
    	
    	// Demonstrates the use of the CustomMousePointer class
    	public class CustomMousePointerDemo extends Sprite{
    		private var pointer:CustomMousePointer;
    		
    		// Constructor
    		public function CustomMousePointerDemo(){
    			// Create a new CustomMousePointer object and add it to the display list.  The act of
    			// adding the customMousePointer to the display list automatically replaces the system mouse pointer
    			// with the CustomMousePointer object
    			pointer = new CustomMousePointer();
    			addChild(pointer);
     		}
    	}
    }
    The StageDetector class uses the stage instance variable to determine whether an object is on the display list or not. My guess is that this is where the problem is but I can't figure out why. Here is the StageDetector

    Code:
    // File StageDetector.as
    
    package {
    	import flash.display.*;
    	import flash.events.*;
    	
    	// Monitors a specified display object to see when it is added to or removed from the stage, and broadcasts the corresponding custom events
    	// StageDetector.ADDED_TO_STAGE and StageDetector.REMOVED_FROM_STAGE.
    	
    	// USAGE:
    	// var stageDetector:StageDetector = new StageDetector(someDisplayObject);
    	// stageDetector.addEventListener(StageDetector.ADDED_TO_STAGE, addedToStageListenerFunction);
    	// stageDetector.addEventListener(StageDetector.REMOVED_FROM_STAGE, removedFromStageListenerFunction);
    	
    	public class StageDetector extends EventDispatcher {
    		// Event Constants
    		public static const ADDED_TO_STAGE:String = "ADDED_TO_STAGE";
    		public static const REMOVED_FROM_STAGE:String = "REMOVED_FROM_STAGE";
    		
    		// The object for which ADDED_TO_STAGE and REMOVED_FROM_STAGE events will be generated
    		private var watchedObject:DisplayObject = null;
    		
    		// The root of the display hierarchy that contains watchedObject
    		private var watchedRoot:DisplayObject = null;
    		
    		// Flag indicating whether watchedObject is currently on the display list
    		private var onStage:Boolean = false;
    		
    		// Constructor
    		public function StageDetector(objectToWatch:DisplayObject) {
    			// Begin monitoring the specified object
    			setWatchedObject(objectToWatch);
    		}
    		
    		// Begins monitoring the specified object to see when it is added to or removed from the display list
    		public function setWatchedObject(objectToWatch:DisplayObject):void {
    			// Track the object being monitored
    			watchedObject = objectToWatch;
    			
    			// Note whether watchedObject is currently on the display list
    			if (watchedObject.stage != null) {
    				onStage = true;
    			}
    			
    			// Find the root of the display hierarchy containing the watchedObject, and register with it for ADDED/REMOVED events.
    			// By observering where watchedObject's root is added and removed we'll determin whether watchedObject is on or 
    			// off the display list.
    			setWatchedRoot(findWatchedObjectRoot());
    		}
    		
    		// Returns a reference to the object being monitored
    		public function getWatchedObject():DisplayObject {
    			return watchedObject;
    		}
    		
    		// Frees this StageDetector object's resources.  Call this before discarding a StageDetector object.
    		public function dispose():void {
    			clearWatchedRoot();
    			watchedObject = null;
    		}
    		
    		// Handles Event.ADDED events targeted at the root of watchedObject's display heirarchy
    		private function addedListener(e:Event):void {
    			// If the current watchedRoot was added...
    			if(e.eventPhase == EventPhase.AT_TARGET) {
    				// ...check if watchObject is now on the display list
    				if(watchedObject.stage != null) {
    					// Note that watchedObject is now on the display list
    					onStage = true;
    					// Notify listeners that watchedObject is now on the display list
    					dispatchEvent(new Event(StageDetector.ADDED_TO_STAGE));
    				}
    				// watchedRoot was added to another container, so there's now a new root of the display hierarchy containing watchedObject
    				// Find that new root, and register with it for ADDED and REMOVED events.
    				setWatchedRoot(findWatchedObjectRoot());
    			}
    		}
    		
    		// Handles Event.REMOVED events for the root of watchedObject's display hierarchy
    		private function removedListener(e:Event):void {
    			// If watchedObject is on the display list...
    			if(onStage) {
    				//...check if watchedObject or one of it's ancestors was removed
    				var wasRemoved:Boolean = false;
    				var ancestor:DisplayObject = watchedObject;
    				var target:DisplayObject = DisplayObject(e.target);
    				while (ancestor != null) {
    					if (target == ancestor) {
    						wasRemoved = true;
    						break;
    					}
    					ancestor = ancestor.parent;
    				}
    				
    				// If watchedObject or one of it's ancestors was removed
    				if(wasRemoved){
    					//...register for ADDED and REMOVED events from the removed object
    					// Which is the new root of watchedObject's display hierarchy
    					setWatchedRoot(target);
    					
    					// Note that watchedObject is not on the display list anymore
    					onStage = false;
    					
    					// Notifiy listeners that watchedObject was removed from the stage
    					dispatchEvent(new Event(StageDetector.REMOVED_FROM_STAGE))
    				}
    			}
    		}
    
    		// returns the root of the display hierarchy that currently contains watchedObject
    		private function findWatchedObjectRoot():DisplayObject {
    			var watchedObjectRoot:DisplayObject = watchedObject;
    			while(watchedObjectRoot != null){
    				watchedObjectRoot = watchedObjectRoot.parent;
    			}
    			return watchedObjectRoot;
    		}
    		
    		// Begins listening for ADDED and REMOVED events targeted at the root of watchedObject's display hierarchy
    		private function setWatchedRoot (newWatchedRoot:DisplayObject):void {
    			clearWatchedRoot();
    			watchedRoot = newWatchedRoot;
    			registerListeners(watchedRoot);
    		}
    		
    		// Removes event listeners from watchedRoot, and removes this StageDetector's reference to watchedRoot
    		private function clearWatchedRoot():void {
    			if (watchedRoot != null) {
    				unregisterListeners(watchedRoot);
    				watchedRoot = null;
    			}
    		}
    	
    		// Registers ADDED and REMOVED event listeners with watchedRoot
    		private function registerListeners(target:DisplayObject):void {
    			target.addEventListener(Event.ADDED, addedListener);
    			target.addEventListener(Event.REMOVED, removedListener);
    		}
    		
    		// Unregisters ADDED and REMOVED event listeners from watchedRoot
    		private function unregisterListeners(target:DisplayObject):void {
    			target.removeEventListener(Event.ADDED, addedListener);
    			target.removeEventListener(Event.REMOVED, removedListener);
    		}
    	}
    }
    I'm pretty sure that there are Event.addedToStage and Event.removedFromStage event types now but I wanted to keep with the book.

    Thank you for your help.

  2. #2
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    You left out the class which actually has the error. But I can guess it anyway. In the constructor for CustomMousePointer you have a line like this:
    Code:
    StageDetector.registerListeners(stage);
    Though that seems silly, since the whole point of StageDetector seems to be to do stuff when something is added to the stage, and the stage can't be added to the stage.

    Post the constructor of CustomMousePointer. And you're right, there are ADDED_TO_STAGE and REMOVED_FROM_STAGE events which you should use in place of this StageDetector thing.

  3. #3
    Junior Member
    Join Date
    Feb 2009
    Posts
    3
    Hi 5TonsOfFlax,
    Thank you for your reply. I left out the CustomMousePointer class cause all it does is pass a reference of itself to a StageDetector instance. It looks like this:
    Code:
    var stageDetector:StageDetector = new StageDetector(this);
    stageDetector.addEventListener(StageDetector.ADDED_TO_STAGE, addedToStageListener);
    stageDetector.addEventListener(StageDetector.REMOVED_FROM_STAGE, removedFromStageListener);
    I think I will have to fore go the StageDetector and just define listener's for the built in events instead. See if that works.

    Thanks again!

    Justin

  4. #4
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Ah, now that I actually trace through StageDetector, I see the problem. It's in findWatchedObjectRoot. Since the object passed in has no parent at the time, it should be the watchedObjectRoot, but that function actually returns null in that case. That null is then passed to registerListeners, causing the error.
    It could be fixed like this:
    Code:
    	// returns the root of the display hierarchy that currently contains watchedObject
    	private function findWatchedObjectRoot():DisplayObject {
    		var watchedObjectRoot:DisplayObject = watchedObject;
    		while(watchedObjectRoot.parent != null){
    			watchedObjectRoot = watchedObjectRoot.parent;
    		}
    		return watchedObjectRoot;
    	}
    But yeah, use the built in events instead.

  5. #5
    Junior Member
    Join Date
    Feb 2009
    Posts
    3
    AH of course! Thank you! And now that I know where to look I realize that I forgot the ".parent"; it was written in the book! I'll have to be more careful

    Thanks!

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