AS3 call a just added element - actionscript-3

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

Related

AS3 Multiple Rollover objects

example image
Very new to AS3. Sorry if this question is really basic, I tried looking around for the right answer but only found semi-related questions. Please help!!
Objective: I want multiple rollover MovieClips on the same stage that play out their animations independently.
So far, I have only 1 MovieClip object that behaves properly. If I add another, the first one behaves properly but the second doesn't appear at all. I understand that it's probably only calling the instance that I first dropped into the stage and that I need to change my code to have a "master" or parent MovieClip and that the instances should be the children, but I'm not sure how to write that in code. Eventually, the idea is that I add my children movieclips, and then slightly change the content in each clip.
My code so far:
import flash.events.MouseEvent;
clip_boxes.removeEventListener(MouseEvent.ROLL_OUT, clipOut);
clip_boxes.addEventListener(MouseEvent.ROLL_OVER, clipOver);
function clipOver(event:MouseEvent):void {
clip_boxes.addEventListener(MouseEvent.ROLL_OUT, clipOut);
clip_boxes.removeEventListener(MouseEvent.ROLL_OVER,clipOver);
clip_boxes.gotoAndPlay("Over");
};
function clipOut(event:MouseEvent):void {
clip_boxes.addEventListener(MouseEvent.ROLL_OVER, clipOver);
clip_boxes.removeEventListener(MouseEvent.ROLL_OUT, clipOut);
clip_boxes.gotoAndPlay("Out");
};
There are a few ways you can do this. I'll list in order of worst to best.
Manually add listeners to each instance.
When you drag a new MovieClip onto the timeline, you need to give it an instance name (found in the properties panel). I'm not sure if clip_boxes is a parent timeline that you intend to have all your movie clips on, or if it is one of your movie clips itself.
Assuming you have 3 clips with the instance names: MC1,MC2,MC3, you could do this (on the first frame of the timeline that contains them)
MC1.addEventListener(MouseEvent.ROLL_OVER, clipOver);
MC2.addEventListener(MouseEvent.ROLL_OVER, clipOver);
MC3.addEventListener(MouseEvent.ROLL_OVER, clipOver);
//If you had a whole bunch, you could also use a loop to add all the listeners
//you use event.currentTarget to get a referce to the object the listener was attached to - this way you only need this one handler function
function clipOver(event:MouseEvent):void {
MovieClip(event.currentTarget).addEventListener(MouseEvent.ROLL_OUT, clipOut);
MovieClip(event.currentTarget).gotoAndPlay("Over");
};
function clipOut(event:MouseEvent):void {
MovieClip(event.currentTarget).removeEventListener(MouseEvent.ROLL_OUT, clipOut);
MovieClip(event.currentTarget).gotoAndPlay("Out");
};
Use Inheritance
This would involve creating a base class file (.as file) that you can then attach to all your MovieClips so they inherit all the code within. Here is an example of a class file that would do this for you: (lets assume this is a file called SubClass.as in your root directory)
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class SubClass extends MovieClip {
public function SubClass(){
this.addEventListener(MouseEvent.ROLL_OVER, rollOver,false,0,true);
}
public function rollOver(event:MouseEvent):void {
this.addEventListener(MouseEvent.ROLL_OUT,rollOut,false,0,true);
this.gotoAndPlay("Over");
}
public function rollOut(event:MouseEvent):void {
this.removeEventListener(MouseEvent.ROLL_OUT,rollOut,false);
this.gotoAndPlay("Out");
}
}
}
Now, when you create your movieClips (or right click in the library and select properties), you can set a baseClass for them. If you set the base class to the class above, they automatically use the code above and have the mouse over/out attached. (as long as they have the Out/Over frame labels it will just work).
Can you also post the code where you add clip boxes to the stage? Did you add them in the GUI by dragging and dropping or in code?
If so, you might need to make instances of each of the clip boxes inside the larger movieclip that contains all of them together. Then you'll need to refer to each one with clip_boxes.box1, etc.
EDIT:
Oh, I see you had an image there. My bad. Make sure you give each clip box its own unique instance name. You'll need to have clip_box_1, clip_box_2, etc. Then in code you use clip_box_1.addEventListen.....etc.

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()

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

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.

Is removeChild enough to completely remove a movieclip from Flash Player memory?

Will this line
clip.removeChild(clip.getChildAt(0));
completely remove the child of clip at 0 index? I read somewhere you should set to null to all the references to that clip, but I have no other reference in my code. The clip at 0 was added via a regular addChild().
For the garbage collector to swipe your object you should:
-not have any other reference to the object throughout your code
-the object shouldn't be part of any collection (like Array or Vector)
-the current reference should be set to null
Be sure to pay extra attention to the second condition, the most common situation when the object is part of a collection you can't control directly is when it had a listener attached to it and when is part of the display list. On top of that, there are other situations when the object is part of a collection you can control, don't forget to remove it form there too.
Also, to force the garbage collector to swipe your object (only for testing, not production), you can use System.gc() and then check the memory with System.privateMemory
if you're removing them in a loop, do it like this:
while (clip.childNum > 0)
{
var child:MovieClip = clip.getChildAt(0);
clip.removeChild(child);
// remove all listeners
child.removeEventListener(...);
child = null;
}
if "child" is a custom class you may call a kill() method to clean everything up inside your class/instance.
Not sure, if you still have reference on the clip, garbage collector may distroy the object, try to remove an event listener and force the clip reference to null.
If you have no references, no listeners or any other handle to the clip then it will eventually be garbage collected. Due to the way the GC works it might not immediately be removed from memory. Your DisplayObject will however immediately be removed from the display list.
But if you do something like this in one of your classes:
private var mc:MovieClip = new MovieClip();
private function addClip() : void {
mc.addEventListener(Event.ENTER_FRAME, myListener);
myClass.addChild(mc);
}
Then you'll want to properly remove mc like this:
private function removeClip() : void {
mc.removeEventListener(Event.ENTER_FRAME, myListener);
myClass.removeChild(mc);
mc = null;
}

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);