Targeting movieclip from an AS3 class file

Now that more and more flash developers are writing AS3 as class file, rather than codes sitting in the timeline, it is important to know how to target movieclip from within an AS3 class file.

For document class file, that is easy and is similar to how to target instance from within the main timeline. So if there is a movieclip named myClip_mc, then it is targeted simply as myClip_mc or this.myClip_mc in the .as document class file.

But what if the .as file is not the document class file, but simply a class used by the document class?

Now try the following:

1. Create a Test.fla and a movieclip symbol named “BlackBox” in the movie library.

2. At the symbol properties panel, turn on Export for Actionscript. The class name would be “BlackBox”.

3. Specify the document class (Test) in the properties panel.

4. Create the Test.as document class with the following code. Note the use of the static variable.

package
{
 import flash.display.MovieClip;
 
 public class Test extends MovieClip
 {
  public static var blackbox_mc:MovieClip = new BlackBox();
  
  public function Test()
  {
   this.stage.addChild(blackbox_mc);
   var myTest:Control = new Control();
  }
 }
}

5. Create the Control.as class file with the following code:

package
{
 public class Control
 {
  public function Control()
  {
   Test.blackbox_mc.y = 100;
  }
 }
}

Now the above technique would work. As noted above the trick is to create a static variable so that it can be referenced from the Control.as file.

But what if the movieclip instance is not programmatically created but instead is created by dragging the symbol from the library window? I don’t know the answer yet. If anyone has some suggestion, please share it here. 🙂

Advertisements

~ by brianchau on January 15, 2008.

31 Responses to “Targeting movieclip from an AS3 class file”

  1. I personally would avoid creating static vars like that. If the object isn’t inside the class a general rule to follow would be that the class shouldn’t have access to it. Instead your class should dispatch an event, which can be listened to, to update objects elsewhere.

    I see you have a Control class here. We would usually create a View and Controller. Our controller has a reference to the View, and the View has methods the controller can invoke. When these methods are invoked, the View updates itself.

  2. I explored some of this… not beign in a document class complicates stuff sometimes… read this post I made having troubles with the as3 “attachmovie” (new instanceName()) and it’s sollution. in the third post.
    http://www.flashfocus.nl/forum/showthread.php?t=39955

  3. as it is in dutch.. the clue of the attachMovie sollution comes down to this.
    public function AttachMovie(id:String):Class
    {
    return Class(Object(_loader.contentLoaderInfo).applicatio nDomain.getDefinition(id));
    }

  4. As Tink says, it’s normally better to encapsulate the functionality of each class using events and public methods instead of exposing the internals.

    For this simple example, you might rewrite it something like…

    Test.as
    >>
    package
    {
    import flash.display.MovieClip;

    public class Test extends MovieClip
    {
    private var blackbox_mc:BlackBox;

    public function Test()
    {
    blackbox_mc = new BlackBox();
    this.stage.addChild(blackbox_mc);
    var myTest:Control = new Control(this);
    }

    public function positionBlackBox(x=null,y=null) : void {
    blackbox_mc.x = (x==null)?blackbox_mc.x:x;
    blackbox_mc.y = (y==null)?blackbox_mc.y:y;
    }
    }

    }
    <>
    package
    {
    import flash.display.MovieClip;
    public class Control
    {
    private var view:MovieClip;
    public function Control(mc:MovieClip)
    {
    view = mc;
    view.positionBlackBox(null,100);
    }
    }
    }
    <>
    package
    {
    import flash.display.MovieClip;

    public class Test extends MovieClip
    {

    public function Test()
    {
    var myTest:Control = new Control(this);
    }

    public function positionBlackBox(x=null,y=null) : void {
    blackbox_mc.x = (x==null)?blackbox_mc.x:x;
    blackbox_mc.y = (y==null)?blackbox_mc.y:y;
    }
    }

    }
    <<

    As the blackbox_mc is already on the views stage flash auto creates the reference, so you can just use blackbox_mc without creating it.

  5. […] is a reply to Brian Chau’s post here, but my comment didn’t go through too well, so I’ll repeat it […]

  6. wow, that broke! note to self avoid < and > in comments you can’t preview 🙂

    I’ve posted it on my blog instead, you may want to remove the mess above…

    http://www.dustypixels.com/blog/2008/01/15/targeting-movieclip-from-an-as3-class-file-reply/

  7. Thanks guys for all your inputs. 🙂

  8. I saw a blog you had back in August 07 about the HTC homescreen plugin (screenshots included), I thought it was very impressive. I just purchased an AT&T Tilt and would like to have that same interface. I have downloaded the relevant files (at least I think so), but I cannot seem to get it EXACTLY like your screenshots. I still get the greyish background instead of the crisp black that you have. I have tried a few things but to no avail. Could you please tell me the EXACT files and steps you took to get that. I would greatly appreciate it.

    TC

  9. TC, I used the Glossy Black Bar cab to change the default grey bars to glossy black bar. The Cab is for HTC Hermes. Not sure if it would work for Kaiser (Tilt). You can download it at:

    http://rapidshare.com/files/86394842/Glossy_Black_Bars.cab.html

    Alternatly, head to the XDA forum. There are a few Kaiser ROMs out there with black themes.

    http://forum.xda-developers.com/forumdisplay.php?f=378

  10. HelloI am a green flash designer. I am trying to link a swf file to a button with “0” luck.
    I tried about 40 scripts and none worked, Please can you help?
    My button is labl drawings_btn (instance) and the swf labe drawingsMovie.
    Sincerly,
    Pnina

  11. pnina, you would need to use the Loader class and the URLrequest class to load the swf. Script would be like the following:

    var swfContent:Loader = new Loader();
    stage.addChild(swfContent);

    load_btn.addEventListener(MouseEvent.CLICK, doClick);
    function doClick(e:MouseEvent):void
    {
    var url:URLRequest = new URLRequest(“LensFlare.swf”);
    swfContent.load(url);
    }

  12. I’m also green with an instance referencing question. I have a movieClip (Button_mc) inside a movieClip (Menu_mc). I’m trying to give the Button_mc an instance name. I can name it if a create a new instance with addChild, but how can I give the existing Button_mc a name while it is already located inside Menu_mc?

    Thank you,
    Donavan

  13. Thank you for the help I know you would have given me, but I figured it out. I just had to give Button_mc an instance name in the actual Menu_mc movieClip. Wow I should have known that.

    -Donavan

  14. Thanks for this article. It helped me to get a working example of the document class + MovieClip combination and then experimented with breaking it. I wrote a explanation of the the ways it can break and the errors that are produced:
    http://focusondistinction.blogspot.com/2009/01/pain-of-flash-cs3-actionscript-3.html

  15. Has anyone worked this out?

    ‘But what if the movieclip instance is not programmatically created but instead is created by dragging the symbol from the library window?’

    How would you access the movieclip if the .as file is not the document class file?

  16. I thought I’d experiment with paul’s comment. I tried taking my document class and instantiate it from a frame script. I failed. I found several new errors but couldn’t get it to work.
    import com.efi.LessScreen.LessScreensClazz;
    import flash.display.MovieClip;
    var abc = new LessScreensClazz();

    I kept getting the error “1017: The definition of base class MovieClip was not found.”

    I suspect there needs to be a movie clip in my Library that matches the class that I’m instantiating. I was able to remove the ‘extends MovieClip’ from my class definition and then instantiate the class but then that class knew nothing about the movieclips on the stage nor the stage itself.

    My conclusion is that it’s wise to use the document class.

    Curtis Morley has written extensively on Flash error codes and this might be of help to folks.
    http://curtismorley.com/2007/08/13/flash-cs3-flex-error-2136-the-swf-file-fileccurtismflashmatchwordsgametestswf-contains-invalid-data/
    http://curtismorley.com/2007/07/

  17. If there is a movieclip instance of blackbox_mc manually added to the .fla

    A document class Test.as file as:

    package
    {
    import flash.display.MovieClip;

    public class Test extends MovieClip {

    var myTest:Control;

    public function Test() {
    init();
    }

    public function init():void {
    myTest = new Control();
    addChild(myTest);
    }

    }
    }

    Another class file called Control.as has:

    package
    {
    import flash.display.MovieClip;
    import flash.events.Event;

    public class Control extends MovieClip {

    public function Control() {
    addEventListener(Event.ADDED_TO_STAGE,go);
    }

    private function go(evt:Event):void {
    removeEventListener(Event.ADDED_TO_STAGE,go);
    MovieClip(root).blackbox_mc.x = 400;
    }

    }

    }

    Using MovieClip(root) the Control.as file can then target the movieclip on the stage. Or if the class extends Sprite instead, Sprite(root).

    This code works, but I’m wondering if this is a good approach?

  18. While your solution may work, it seems to have some problems. The posts by Tink and Adam above provide some explanation why. Referencing a movie clip like you have done seems like using a global reference and it hard codes the movieclip name to the class, thus tightly coupling the movieclip to the class. In Adam’s post, he passes a reference to blackbox_mc into the control class constructor. The control class is then more general purpose and can be re-used by passing it a different movieclip reference. Adam also puts the code for manipulating the movieclip position into the document class and has the control class call that method through the reference. In some sense, the control class has then some inflexibilty because it knows the method name. The upside is that all the code dealing with manipulation of blackbox is centralized in the document class which helps the developer keep track of things as the program grows. Another good practice is to write an interface for all classes that instantiate control. That interface would mandate a position method that the control class could call.

  19. Thanks for the feedback. I agree the class should be more flexible.
    And would be better with references passed to it, so that is could be reused. Maybe the following is better?

    Still have a movieclip instance of blackbox_mc manually added to the .fla

    The main documnet class is Test.as:
    package
    {
    import flash.display.MovieClip;

    public class Test extends MovieClip {

    private var myClass:MovieClip;

    public function Test() {

    myClass = new Control(this);
    init();

    }

    public function init():void {

    myClass.go(“blackbox_mc”, 400);

    }

    }
    }

    The other class .as file called Control.as:

    package
    {
    import flash.display.MovieClip;
    import flash.events.Event;

    public class Control extends MovieClip {

    private var mainTimeLine:MovieClip;

    public function Control(_mainTimeLine) {
    mainTimeLine = _mainTimeLine;
    }

    public function go(_mc:String, _xpos:Number):void {
    mainTimeLine.getChildByName(_mc).x = _xpos;
    }

    }

    }

  20. I’d argue that it is easier to add items dynamically than manually. The benefit of manual is that it potentially saves some effort positioning. Adobe makes it hard enough to tie code to their authoring tool that it’s worth considering doing Flex.

  21. […] Targeting movieclip from an AS3 class file « Brian Chau (tags: flash mc_class) […]

  22. paul… I’ve tried your example and it worked, but only for one object. “MovieClip(root).blackbox_mc.x = 400;” works well. But if I create a second object, make it a Movie Clip Symbol and give it the instance name ‘chow’, the program throws an error and doesn’t work when I access it by “MovieClip(root).chow.x = 100;”. But the program will eventually access that instance and the program will work if I delete the first code “MovieClip(root).blackbox_mc.x = 400;”. So only one instance can be accessed at a time. How can I access hundreds of instances easily?

  23. I can get the above examples working when the movieclip symbol is placed on the fla timeline in frame 1 in the IDE. But if the fla’s timeline is, say, 60 frames long and I place the movieclip on frame 30, in my document class when I listen for the arrival of frame 30 and then reference that movieclip I get “Error #1009: Cannot access a property or method of a null object reference”.

    How would I reference that movieclip. Obviously, it has not been instantiated until frame 30 therefore the Document Class doesn’t know about it (or does it?) but how can I prepare the document class to know about it and therefore control it?

  24. That error (1009) indicates that the frame hasn’t loaded yet. If you are trying to script things on that frame before it loads, you will get that error. There are events for the frame that you need to listen for. I forget the names of those events but there are a lot of posts on the web about this error.

  25. You cannot target movieclip from a different class if the movie clip is just placed on the stage. I know some of you will say it can be done, but I will post an example later. I have wasted an entire day trying to do it in several ways.

  26. To target a movie clip from a class that is on the stage use:

    var myContent:MovieClip = MovieClip(parent).mcContent;

    then you just call with the new variable. ie.

    Tweener:
    Tweener.addTween(myContent, {alpha:0, time: 1});

    Position:
    myContent.x += 50;

    Loading another swf into it:
    while (myContent.numChildren) {
    myContent.removeChildAt(0);
    }
    var swfLoader:Loader = new Loader();
    var swfURL:URLRequest = new URLRequest(url);
    swfLoader.load(swfURL);
    myContent.addChild(swfLoader);

  27. Thank you very much buddy, that really helped me. I was fighting with a gallery. thanks a lot

  28. Hi,

    I am trying to get around AS3 but I seem to have a lot of difficulties on understanding some things. I have this problem:

    Have a main.fla with a Main.as file that adds all my homepage items to display on stage through the help of another .as file.

    All items/movieclips are correctly placed on stage. One of them is the MC (containerMC) to where I would like to load all my external swf’s.

    I am calling all my external swf’s through a function inside my menuMC in the main.fla and of course I just can’t access to the containerMC.

    I decided to write here because I have been reading the posts but quite frankly, I am just very lost… Could someone help me understanding better how to resolve this question?

    I really am not sure if I have to use root, parent and getChildByName or whatever. I’ve tried all of them and none work. Maybe I’m misplacing something :/

    Many thanks in advance!!

    filipa

  29. Why have you got:
    public class Test extends MovieClip
    {
    public static var blackbox_mc:MovieClip = new BlackBox();

    and not:
    public class Test extends BlackBox
    {

    BlackBox is already a MovieClip and so having extends MovieClip becomes redundance given that you have now got two instances when you are only attaching one of them to the stage in your example code.

    The “extends BlackBox” method solves all your problems as you can simply put this.y = 100; on top of being able to use the overide keyword to take greater control of the MovieClip being processed.

    Also static should be treated like a global variable/function when used. As such this breaks OOP. There are very rare cases where static is useful, this isn’t one of them.

  30. ‘But what if the movieclip instance is not programmatically created but instead is created by dragging the symbol from the library window?’

    Incase anyone still wonder – this is how:

    Test.as:

    package{
    import flash.display.MovieClip;
    public class Test extends MovieClip{
    public static var blackbox:MovieClip;
    public function Test()
    {
    blackbox = write_actual_instance_name_of_box_here;
    var myTest:Control = new Control();
    }
    }
    }

    Control.as:

    package{
    public class Control {
    public function Control() {
    Test.blackbox.y = 200;
    }
    }
    }

  31. It’s very simple to find out any topic on web as compared to
    books, as I found this article at this web site.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: