AS3 stage.addChild / stage.removeChild << Must be child of caller - actionscript-3

If im usin function to add a mc to the stage like so:
var myChild:MC= new MC();
function somefunc()
{
stage.addChild(myMC)
}
but when I try to remove the mc by:
stage.removeChild(myMC)
I get The supplied DisplayObject must be a child of the caller error...
any suggestions or work arounds?

Your code should work if the item is on the stage. Perhaps qualifying it with a conditional statement like so:
if (myMC.stage != null)
stage.removeChild(myMC);
Alternatively you could use the following code but it is probably not best practice.
if (myMC.parent != null)
myMC.parent.removeChild(myMC);

The problem is not with removeChild. It's with the displaylist. If you check the parent property of the displayobject, when you call "removeChild" it will be null.
Why does it become null could be because of lots of reasons:
Parent is nulled before the child.
The child or parent have event listeners that won't let them die.
The Display Object is really not the instance you're trying to remove. THIS one can be very tricky to find out. Look at the "name and parent properties" of the variable you're trying to remove while calling removeChild.

You could try hiding and showing the movieClip, if possible.
I think its a bit faster than removing and adding consistantly, code permitting.
Keep in mind this is just a suggestion, someone smarter than me outta be able to help you out..

You could also use this fail safe:
if(myMC.parent) myMC.parent.removeChild(myMC);

I could fix this problem by simply removing every EventListeners I added to that object before removing it.

Related

Remove Child AS3

I'm trying to remove a child movieclip but it's always get an error. I already tried different way and nothing works.
Here is my print screen. The Movieclip i want to remove is movieclip1 that is inside the movieclip playerPaddle.
Any help please.
my code to remove:
if(playerPaddle.movieclip1.hitTestObject(ball)){
playerPaddle.movieclip1.removeChild(movieclip1);
}
Error Message:
Dialog box saying dismiss all or continue - cannot converto movieclip1$ to flash.display.DisplayObject
If i understood correctly, you're trying to remove movieclip1 from playerPaddle object.
To do this you have to call:
if(playerPaddle.movieclip1.hitTestObject(ball)){
playerPaddle.removeChild(playerPaddle.movieclip1);
}
And That is because playerPaddle is parent object of movieclip1 hence, calling removeChild on parent object will work perfectly.
While Kuba's answer brings up an issue with the code you've provided, but I think the issue you are facing right now is that movieclip1 object that is passed as parameter to playerPaddle.movieclip1.removeChild(...) isn't a movieclip1. If I have to venture a guess, it most probably is null.
Can you try:
if(playerPaddle.movieclip1.hitTestObject(ball))
{
playerPaddle.removeChild(playerPaddle.movieclip1);
}
(I've included the suggestion by Kuba too).
the following may help you
if(this.parent) this.parent.removeChild(this);
you can replace this with the proper child and have the same result. like:
if(ball.parent) ball.parent.removeChild(ball);
Kuba is almost correct, but movieclip1 will not be in scope. You still need to point to movieclip1 which is an object belonging to playerPaddle.
if(playerPaddle.movieclip1.hitTestObject(ball))
{
playerPaddle.removeChild(playerPaddle.movieclip1);
}
If your removing the child you also need to remove the EventListener that is listening to the child. If you remove the child object and the event listener is still checking for it, you will get an error. You can nest the function in a check statement like this
if(playerPaddle)
{
if(playerPaddle.movieclip1.hitTestObject(ball))
{
playerPaddle.removeChild(playerPaddle.movieclip1);
}
}

AS3 - Loading multiple videos into the same container - addChild removeChild

This is a function that loads a specific video into a MovieClip container at 0.0 using a video class.
public var mainVideo:SimpleVideo;
public function loadVideo(videoString:String) :void{
mainVideo = new
SimpleVideo("videos/"+videoString+".flv","",true,video_container.positionMc);
video_container.addEventListener(MouseEvent.MOUSE_DOWN,controlVideoPlayer);
addChild(mainVideo);
trace('adding new video to container');
}
I'd like to preferably check, each time a video is loaded, to see if there already is another video loaded. And if there is, then remove it, and add the new video.
I've tried using removeChild() in a variety of ways, but it doesn't seem to work correctly.
Would I use removeChild(mainVideo)? video_container.removeChild(mainVideo)?
And how would I be able to check if there was already an existing mainVideo?
Any help would be greatly appreciated!
-Update-
If I try and use removeChild(mainVideo) I get this error:
TypeError: Error #2007: Parameter child must be non-null. at
flash.display::DisplayObjectContainer/removeChild() at
Main/removeVideo() at MethodInfo-127()
If you add the video into a container movieclip rather than onto stage, and that container only has just one instance of SimpleVideo in its display list at a time, you could do:
if( myVideoContainer.numChildren > 0 )
{
myVideoContainer.removeChild( myVideoContainer.getChildAt( 0 ) );
}
A bigger issue though is how the SimpleVideo class you are using cleans itself up. Most video classes have a cleanup or kill function that removes the listeners and cleans up the netStream. I would think you'd need to call something like that as well as removing the video instance from the container.
I hope this respone may help you
--> Would I use removeChild(mainVideo) ? video_container.removeChild(mainVideo) ?
you should use removeChild function but you need to know who is the parent of mainVideo and call this function of his parent, in your case, I think, video_container is not the parent because is a variable near mainVideo and you add mainVideo to the instance of the class which has loadVideo function
sometimes you can use mainVideo.parent.removeChild(mainVideo), not the best approach but it works, it's better to know who is the parent and call function removeChild() explicitly on that "parent"
--> would I be able to check if there was already an existing mainVideo?
well, you can do a simple if(mainVideo != null) { .. } because in function loadVideo you create new instances each time, that means if you called at least one time this function then if condition should be true that means you have already an existing mainVideo
--> TypeError: Error #2007: Parameter child must be non-null.
that means your mainVideo is not instantiated, because I guess you have not called loadVideo() yet, that's why #putvande asked you to provide more code, we need to see where and when you call removeChild()

Issues correctly removing childs from flash

hey im having issues removing my enemy blocks. at the moment if i hit everyone of them everything is fine but when i avoid one i get an error message of
ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
at flash.display::DisplayObjectContainer/removeChild()
at EnergyJump/onTick()
at flash.utils::Timer/flash.utils:Timer::_timerDispatch()
at flash.utils::Timer/flash.utils:Timer::tick()
here is my code i have:
public function onTick( timerEvent:TimerEvent ):void
{
//if ranrom number is than than i
if ( Math.random() < i )
{
//place block on stage at location X=550, Y=330
var randomX:Number = Math.random() * 550;
var newBlock:Blocks = new Blocks( 550, 335 );
army.push( newBlock );
addChild( newBlock );
//increase speed of spawn
i = i + 0.0001;
}
//move blocks in correct direction
for each ( var block:Blocks in army )
{
block.move();
//if block is hit then remove health and remove child object
if ( avatar.hitTestObject( block ) )
{
hp.checkHP(20);
army.splice(army.indexOf(block), 1);
removeChild( block );
}
}
}
can anyone help me, i dont really know what slice is to be honest or how to use it...
You should have a look at the documentation for Array.splice() here.
The first argument needs to be the index (0, 1, 2 etc.) of the item you want to remove, not the item itself. Flash is trying to read block as an integer, but it defaults to 0, so instead of removing the block that has been hit it's just removing the first block in the list. Try this instead:
army.splice(army.indexOf(block), 1);
I assume you have some code which is clearing any remaining blocks in the list at the end of the game, but because the wrong blocks are being removed from the list it's trying to remove some that were actually hit already.
Are you sure there is a corresponding addChild() call for each of those objects that has been made before the call to removeChild()? There's not enough code being shown, at the moment, to be able to really tell what's going on, but also make sure removeChild() isn't being called more than once on the same object without addChild() being called in between each time.
Okay, I had a quick look through your files. It's getting a bit off topic for this question, but I'll list the problems I found. In general though you need to look at the parts Flash is complaining about and make sure you're really working with the right variables (eg. if you write block, try to make sure you know which block Flash is going to look at, and remember that the order matters when you change things.)
It's easy to accidentally remove the wrong items or try to use things that are null, so check each line and think about what each variable actually is at that point (maybe try tracing the variables out too).
In avatarEnterFrame you're checking for blocks that have gone off the side of the screen, but you haven't added a for each loop like in onTick, so when you use block there Flash is looking at your main public var block:Blocks; instead of the blocks in army.
In onPowerTick you need to adjust your splice in the same way as before, so that you remove the powerups object you're checking instead of the item at 0.
In restartGame you're setting gameOverScreen to null just before trying to remove it, so Flash doesn't know what to remove. Make sure you leave setting it to null until you're done with everything else.
I'll post a separate answer for your game over screen problem so that it's in the right place.

AS3 call a just added element

i'm adding a movieclip element ("lastSlide") to an other movieclip element("endLogoButton"). The added element has a child which is a button("endLogoButton"). How can i call that button?
mcSlideHolder.addChild(lastSlide);
/*mcSlideHolder.getChildByName("endLogoButton").buttonMode = true;;
mcSlideHolder.getChildByName("endLogoButton").mouseChildren = false;
mcSlideHolder.getChildByName("endLogoButton").useHandCursor = true;*/
lastSlide.endLogoButton.addEventListener(MouseEvent.CLICK, linkClick);
As a beginner i'm struggling around ... but can't make it work ...
It always tells me that the access to a Nullobject reference is not possible.
Thanks for any advice!
You can either 'dig in' to the nested objects to get to the button instance or you can add event listeners to the button instance before adding it to its parent container then let its click event bubble up.
I'm having a bit of trouble understanding what is nested inside of what in your case but I see you're trying getChildByName. getChildByName only gets a direct child (not a child of a child) by its instance name, (not it's variable name).
Dig in example:
lastSlide.getChildByName("endLogoButton").addEventListener(MouseEvent.CLICK, linkClick);
or
lastSlide.name = "myLastSlide";
mcSlideHolder.getChildByName("myLastSlide").getChildByName("endLogoButton").addEventListener(MouseEvent.CLICK, linkClick);
If lastSlide were placed on the stage visually in the Flash IDE, then you could set the instance name myLastSlide there in the properties panel rather than by setting the name property in as3.
or maybe: try casting the "lastSlide" to a MovieClip like:
MovieClip(mcSlideHolder.getChildByName("lastSlide")).getChildByName("endLogoButton").addEventListener(MouseEvent.CLICK, linkClick);
This worked for me several times when the "possible unreferenced object" error popped up when referencing a movieclip that was clearly added to the stage

combining getChildAt with addChild

i have the following code:
seatContainer.getChildAt(order.seats[i])
i want to add a child to this but it doesnt allow me, i can only add an eventListener to this.
Anyone know how i can add a child to this without using an eventListener?
If I remember correctly, getChildAt() from the container classes (e.g. VBox, HBox, etc.) returns a DisplayObject. This object type does not have methods such as "addChild" -- these methods are introduced further down the inheritance hierarchy.
You'll need to cast the referenced returned by the getChildAt() method to something other than DisplayObject; I believe the method you want is in DisplayObjectContainer:
var child:DisplayObject = seatContainer.getChildAt(order.seats[i]);
(child as DisplayObjectContainer).addChild(your_child_class_here);