2

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

Community
  • 1
  • 1
Leon Gaban
  • 36,509
  • 115
  • 332
  • 529
  • 1
    you do not need to call closeVideo() multiple times. It should be called just once. When initializing you container as it is common to every video. Instead of close video just call closeButtonClicked() which will take care of every thing i.e. clearing the video source, removing videoClass and videoContainer. By calling closeVideo multiple times you are creating multiple handlers for closeButton, Which are causing this runtime error. – bhups Oct 31 '09 at 08:39

5 Answers5

2

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");
    }
Joel Hooks
  • 6,465
  • 4
  • 33
  • 39
  • Still getting error, but movie still working fine... I did notice something now, when I play 1 video, close it play another video close it I get 1 error message. Not refreshing I play another video again and close it I get 2 error messages the same, 3 videos 3 error messages trace out, a hint maybe? – Leon Gaban Oct 30 '09 at 21:37
1

Try this:

 container.removeChild(container.videoContainer);
 container.removeChild(container.vc);
Preston
  • 420
  • 1
  • 5
  • 10
  • Still getting that error, but movie still works fine tho... wondering if I really should be worried about this hmmz – Leon Gaban Oct 30 '09 at 20:21
  • trying this now too: if(videoContainer.parent != null) videoContainer.parent.removeChild(videoContainer); but same results – Leon Gaban Oct 30 '09 at 22:12
1

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.

Allan
  • 3,339
  • 2
  • 21
  • 24
  • Yeah I think there is something else I'm not looking at that is still connected here, tried 3 different ways, all which work great, but that error still lingers – Leon Gaban Oct 31 '09 at 21:15
1

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

Jotham
  • 1,122
  • 1
  • 10
  • 23
  • That was it OMG! Forgot to remove the closeButtonClicked Event! /facepalm removeContainerChildren(); closeBtn.removeEventListener(MouseEvent.MOUSE_UP, closeButtonClicked); ontainer.removeChild(closeBtn); – Leon Gaban Oct 31 '09 at 21:32
1

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

enzuguri
  • 818
  • 5
  • 10
  • I forgot to remove the closeButton event listener! closeBtn.removeEventListener(MouseEvent.MOUSE_UP, closeButtonClicked); – Leon Gaban Oct 31 '09 at 21:33