combining getChildAt with addChild - actionscript-3

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

Related

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

Add a property to a Button or other type of Objects

I always created additional property to MovieCLips using the syntax
myMC.myProperty
without any sort of declaration... But i can use this method only with MovieClips.. What about if i want to add a property to a button or any different type of object? I need to extend the class? Do you can me suggest how? Many thanks
You can add property to movieclips in runtime because MovieClip is dynamic class. If the class is not dynamic, you should extend it to create methods and properties.
Read about dynamic classes.
I tend to create custom classes for nearly everything.
I would extend the relevant class and set up a private var for your new property. You can then pass in the value to the constructor or add a getter/setter method to call externally.
private function _myProperty:int;
public function get myProperty():int
{
return _myProperty;
}
public function set myProperty(newVal:int):void
{
_myProperty = newVal;
}
Getter/setter methods add a few lines of code that may seem unnecessary but on big projects when you find a property is being set and you don't know why, you can put a break point in your set myProperty
Subclass is main solution.
Next works only with mx components (flex sdk 3).
Most components have data : Object property that you can freely use to store data.
Monkey patching sometimes is the only way to go. It allows you to add custom properties to flex sdk classes. I don't think you should use it in your case. But I used it to change core logic that is locked by private keyword in flex sdk.
Hope that helps.

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.

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

How to modify map element key

I have a container that holds map of elements.
class MyContainer{
.....
Map<String,MyElement> elements = new ...
...
}
Each element has name property. The key in the map is the element's name. i.e. the method insert is as follows:
void addElement(MyElement elem){
elements.put(elem.getName,elem);
}
I need to use the map data structure, because I have many read operations based on the element name.
The problem is that I need to support modification of the element's name. Changing element name must derive changes in the map. (insert the element with a new key otherwise I won't be able to find that element)
I have thought about two options:
add setName method to MyElement class that will update the container that its name was changed.
don't add setName method to MyElement class, add rename element method to the container, the container will be in charge of updating both the element name and the key in the map.
Option 1 means I have to maintain reference from each element to the container. (this part of the program should maintain low memory footprint).
What do you say? do you see a better option?
I would fire a property change notification on the setName method of the element and handle it in the container object which is listening that notification.
First of all, note that if MyElement can conceivably be used in a context without MyContainer, then option 1 is out.
MyContainer has an obvious relation with MyElement, since its code references MyElement instances through its map. The reverse is not true: the code in MyElement does not need to reference MyContainer. So option 2 is better.
Perhaps, though, you could go for a third hybrid option:
MyElement has a rename method that only changes its own name, and MyContainer has a rename method which calls MyElement.rename and moves the object in the map to the new key.
If the element is only used in this container.
Put the rename operation on the container.
Make the rename method on the element private so another programmer can't accidentally change just the element and forget to update the container.
Option 2 is the simplest and most efficient, thus my choice.
Clearly you know that, so what's the dillema?
Another option is to make a MyString class, that will serve as both a std::string AND a reference to MyContainer. MyString's modifying methods would be in charge of re-maping, and you'd still have a low footprint. E.g.:
class MyString;
class MyElement {
...
MyString name;
...
};
MyContainer * aContainer = new MyContainer;
new MyElement(MyString("Yaron Cohen",aContainer), ...); /* MyString need to be explicit only upon MyElement construction. takes care of inserting into container. */
...
MyElement * someElement = aContainer["Yaron Cohen"]; /* just std::string for lookup */
someElement->name = "Dana International": /* MyString takes care of remapping */
Note that this option supprts multiple keys and containers as well, e.g. FirstName, LastName (if only these were unique...)
Another option is if MyContainer is a singleton.
One more thing to consider is, how often does name change?