Replacing one movie clip on stage with another on a button press.

Hi, I wish to replace a movie clip with another from the library ( at the same place as the first object) at the press of a button.

So I have 2 movie clips mc_rect for a rectangle, mc_Oval for an oval and a button btn_Press in the library.

mc_rect is displayed on stage along with the button btn_Press. I want that on pressing the button the rectangle be replaced by the oval ( at the place where the rectangle was).

How can this be achieved using code?

Thanks all !

Your question is trickier than it sounds. Theres a number of complications that arise from your set up. Here’s my suggestion:

  1. Make sure your oval and rect movie clips are exported for ActionScript in the library and have class names associated with them. You don’t have to write these classes, just make up their names. I’ll use OvalClip and RectClip respectively.

  2. Create a new, empty movie clip in your library. Replace your mc_rect with this empty clip and rename it to something like mc_shapeContainer. This can also be created with code, but it can be nice to have something to position on the timeline. Also, position it in a way that the center of your rect and oval will line up with the position of this clip.

  3. Put this code on the timeline where you have placed your button and now-empty movie clip:


// create movie clips
var mc_oval:OvalClip = new OvalClip();
var mc_rect:RectClip = new RectClip();

// add the one you want to start off to the container
mc_shapeContainer.addChild(mc_rect);

// set up button to replace it
btn_Press.addEventListener(MouseEvent.CLICK, onPressClicked);

function onPressClicked(event:MouseEvent):void {
	
	// check to see if the rect is there now. it
	// won't be if someone already clicked this
	// button once. Only if its there do we replace
	if (mc_rect.parent === mc_shapeContainer) {
		mc_shapeContainer.removeChild(mc_rect);
		mc_shapeContainer.addChild(mc_oval);
	}
}

One of the things we’re doing here (and this sorta relates to another recent thread) is making sure that we’re keeping all code-affected movie clips in the code. We’re not using the timeline to create a movie clip and then removing it using code instead of the timeline. This helps maintain consistent responsibility of ownership.

You might need to be more responsible depending on what else is happening in this timeline. If the timeline animates and this code gets called repeatedly, you’ll be constantly creating new rect and oval clips which could result in a memory leak. So be aware of that as well.

Additionally, I don’t know what kind of behavior you want if the button is clicked multiple times, but here we have an if condition in the button handler. You can also have an else which toggles and replaces the oval back with the rect. Alternatively, you can remove the event handler all together so no code is run when the button is clicked again.

Oh wow !! Thanks Senocular. I actually thought that this was such a noob question that no one wanted to answer but as you showed it turned out to be quite complex. I too thought it should be very simple. Well thanks a lot for that effort. I will check it out and revert by tomorrow if there is something that I do not understand. I am actually lost with oops in AS3.

Thanks again!

The classic flash way to do this, which could also work, is to make a new movie clip (mc_shapeContainer but not empty, because…), put your rect in frame 1, oval in frame 2, and a stop(); command in the timeline of the first frame. Put this where you had your rect before (and I suggested putting mc_shapeContainer) then, all your button function has to do is call mc_shapeContainer.gotoAndStop(2); Its a lot simpler, using less code (no new this, no add or remove childs), and as far as the whole responsibility thing goes, we’re keeping it within the timeline as it is responsible for both adding and removing the rect and oval clips when you tell it to change frames.

Hi Senocular,

Thanks again ! Yes I had thought of this but wanted to explore the the loading of content as well. I have looked at your oops example too. Makes a good small tutorial on the subject of loading and replacing content.

I also found another great method which puts the movie clips on top of each other on the same frame and then I manipulate the visibility property of either to display and hide them as desired.

While doing that I have run up another wall and would like to ask a related question that I would ask here.

I created a small input text box (instance name - inpText) and because the text boxes cannot have a background color (or can they ?) and I wanted the text box to have a color, I put a small same shape colored rectangle behind the textbox and converted the two into a movie clip. However that combined the textbox and the colored rectangle into a movie and it stopped behaving like an input box and so I cannot input a value into it now. Is there any way for me to get my colored text box to behave like a textbox now and then reference the inpText ?

Thanks loads.

Text fields can have background colors but you cant set them from the tool - fully. There is an option for showing the border around the text, which also sets a solid background (black border, white background) but you have to set the colors with code.

To do it through code (without needing to click the border icon) use:

inpText.background = true; // allow it 
inpText.backgroundColor = 0x0000FF; // set it; hex for blue

the icon will auto set background = true, but it doesn’t set the color for you, well, other than white. So you could click the icon and just set backgroundColor in code.

Otherwise, having a movie clip with a rectangle shape behind a text input shouldn’t break the input box. You might have to change your references from inpText to container.inpText where container is the instance name of the movie clip you created to contain both of them. The only thing I can think of is if you accidentally combined them a button symbol instead of a movie clip symbol.

Thanks loads Senocular, That took care of the issue and I managed to achieve what I wanted.