Question

Happy Pre-Halloween everyone :)

My issue today is a DisplayObject error I'm getting when remove a child object. I have code that will launch(addChild) a video container and video controls as well as add a close button. Now the close button works fine and everything, removing the video and controls and I'm able to choose another video again, but when you click close a 2nd time I get this error:

ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller. at flash.display::DisplayObjectContainer/removeChild()

So I've narrowed down the problem to where I remove the videoContainer (which holds the video object)

My code to play the videos:

public function videoSwitch(videoName):void
{
    nv.closeOut();
    nv.resetNav = false;

    if (!videoPlaying)
    {
        vc = new VideoClass(videoName, videoHolder);
        vc.addEventListener("KillMovie", removePlayer);
        container.addChild(videoContainer);
        container.addChild(vc);
        //container.addChildAt(videoContainer, 1);
        //container.addChildAt(vc, 2);
        videoPlaying = true;
        closeVideo();
    }

    else if (videoPlaying)
    {
        vc.clearSource();
        container.removeChild(videoContainer);
        container.removeChild(vc);

        vc = new VideoClass(videoName, videoHolder);
        vc.addEventListener("KillMovie", removePlayer);
        container.addChild(videoContainer);
        container.addChild(vc);
        //container.addChildAt(videoContainer, 1);
        //container.addChildAt(vc, 2);
        closeVideo();
    }
        trace("videoPlaying = "+videoPlaying+"\r");
}

The close out video player code: You can see in my comments other code I tried, but still getting the error.

function closeVideo():void 
{
    closeBtn.visible = true;
    closeBtn.x = 770;
    closeBtn.y = 20;
    closeBtn.buttonMode = true;
    container.addChild(closeBtn);
    closeBtn.addEventListener(MouseEvent.MOUSE_UP, closeButtonClicked);

    function closeButtonClicked(event:MouseEvent):void 
    {
        vc.clearSource();
        container.removeChild(videoContainer);
        //container.removeChildAt(videoContainer, 1);
        container.removeChild(vc);
        videoPlaying = false;
        closeBtn.visible = false;
    }
}

Now my movie works fine, but I'm worried that this error happening in the background (and showing up in my output window) will eventually cause a problem else where :(

Thanks in advance for any eyes on this one! :)


UPDATE: FIXED! The problem was I remove the kill VC listener, but forgot to remove the stupid Close Button Mouse_Event listener :(

function addCloseButton():void 
{
    container.addChild(closeBtn);
    closeBtn.addEventListener(MouseEvent.MOUSE_UP, closeButtonClicked);

    function closeButtonClicked(event:MouseEvent):void 
    {
        videoPlaying=false;
        vc.clearSource();
        removeContainerChildren(); // <- thx Joel!
        closeBtn.removeEventListener(MouseEvent.MOUSE_UP, closeButtonClicked);
        //^ Forgot this line - thx Jotham!
        container.removeChild(closeBtn);
    }
}

Don't know if this graphic helps but: alt text

Was it helpful?

Solution

Do you ever remove the listener? You could well be having it fire multiple times.

OTHER TIPS

here is one approach to avoid the error:

    public function videoSwitch(videoName):void
    {
        nv.closeOut();
        nv.resetNav = false;

        if (videoPlaying)
        {
            vc.clearSource();
            removeContainerChildren()
        }

        addContainerChildren();
        closeVideo();
    }

    protected function removeContainerChildren():void
    {
        if(container.contains(videoContainer))
            container.removeChild(videoContainer);
        if(container.contains(vc))
        {
            container.removeChild(vc)   
            vc.removeEventListener("KillMovie", removePlayer)
        }
    }

    protected function addContainerChildren():void
    {
        videoPlaying = true;
        vc = new VideoClass(videoName, videoHolder);
        vc.addEventListener("KillMovie", removePlayer, false, 0, true); 
        container.addChild(videoContainer);
        container.addChild(vc);

        trace("videoPlaying = "+videoPlaying+"\r");
    }

Try this:

 container.removeChild(container.videoContainer);
 container.removeChild(container.vc);

I have a feeling that it is some other piece of code causing the actual problem. This error would make sense if the videuPlaying variable got changed somewhere else so that you were removing something that did not exist as yet. Maybe check that you are not changing this variable somewhere else.

This is another uber hacky way of doing this, not usually recommended but it will definitly insure that the videoContainer/vc is removed from whichever DisplayList it is on.

private function removeFromStack(target:DisplayObject):void
{
    if (target.parent)
        target.parent.removeChild(target);
}

private function removeVideo():void
{
    removeFromStack(vc);
    removeFromStack(videoContainer);
    vc = videoContainer = null;
}

Just to re-itterate, this is not the preferred way, but it will work without errors. If you start to get a "cannot access null object reference" error, then as previous people have suggested, event listeners or some other dependancies are still held by the DisplayObject's in question.

Hope this helps

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top