6 Replies Latest reply on May 1, 2006 3:59 PM by l_andrew_l

    Using Listener Objects

    l_andrew_l Level 1

      I've recently been trying to wrap my head around the Listener Object (which had always seemed confusing to me). Tutorials made its workings clear, but what they don't seem to touch upon is the WHY and WHEN of using it...

      First, what I've read has said that "Your listener object can be any object, such as an existing object, movie clip, or button instance", but why would you want to use anything other than a Listener Object? Would it make sense syntactically to take a movie clip that you want to respond to a particular event , and add handlers and "addListener" it to the broadcasting object, or is there a reason that you would want to make a standalone Listener Object?


      Also, are Listener Objects only intended for certain classes, such as MovieClipLoader, Selection, etc? Can a normal MovieClip be a broadcaster too?


      And what is the MovieClipLoader class specifically? Does it "exist" on the stage, or is it just an intermediary that then uses a MovieClip? Does it HAVE to be used with the listener object? MovieClips have onLoad() and getBytesLoaded() functions as well...couldn't these be used just as easily to load external content?
        • 1. Re: Using Listener Objects
          Level 7
          l_andrew_l,

          > I've recently been trying to wrap my head around
          > the Listener Object (which had always seemed
          > confusing to me).

          I hear ya. I don't know why, but when I first started using listeners,
          I always had to keep refreshing my memory by looking up the syntax -- again
          and again.

          > Tutorials made its workings clear, but what they don't
          > seem to touch upon is the WHY and WHEN of using it...

          As for when, I believe it simply depends on the structure of the object
          whose events you wish to code against. Some objects are built to need
          handlers, some listeners -- and you find out which is which by looking up
          that object's entry in the ActionScript Language Reference. Caveat: I
          won't swear to this, because I was recently involved in a post where someone
          used listeners in a way that surprised me. He (I think he) was using a
          listener on an object that I had only seen used with handlers.

          > First, what I've read has said that "Your listener
          > object can be any object, such as an existing
          > object, movie clip, or button instance", but why
          > would you want to use anything other than a
          > Listener Object?

          Odd. I've never heard that. I suppose it is *possible* to use almost
          any object as a listener. By and large, most objects in ActionScript --
          including movie clips, buttons, and so on -- inherit from the generic Object
          object. But personally, I would keep it clean and use a generic Object
          instance. Just be be clear, there is no ListenerObject class in
          ActionScript, or anything officially (exclusively) known as a "Listener"
          object. There is an Object class that instantiates generic objects, and
          that's what is typically used to create a "listener object."

          > Would it make sense syntactically to take a movie clip
          > that you want to respond to a particular event, and add
          > handlers and "addListener" it to the broadcasting object,
          > or is there a reason that you would want to make a
          > standalone Listener Object?

          The MovieClip class does not feature an addListener() method, so I'm a
          bit confused by what you're saying, here. MovieClip events only require
          handlers. If you want to assign a function to the MovieClip.onRelease
          event, it's pretty straight forward ...

          mcInstance.onRelease = function() {
          // instructions here
          }

          So in this scenario, there is no reason to create a stand-alone listener
          object. After all, how would you subscribe your listener to a given
          MovieClip instance?

          > Also, are Listener Objects only intended for certain classes,
          > such as MovieClipLoader, Selection, etc? Can a normal
          > MovieClip be a broadcaster too?

          Right, listeners are only for objects that need them, such as
          MovieClipLoader. Again, I believe this is simply due to the way each class
          is written. If I'm wrong, I hope someone will correct me on this.

          Anyway, use the search phrase "addListener method" (with quotes) in the
          Help panel to find the objects that require listeners. Without that
          addListener method, there's nothing with which to "marry" the listener
          object to its broadcaster. Make sense?

          Can a normal MovieClip instance be a broadcaster, too? Sure. The
          MovieClip class is dynamic, which means you can add properties to any
          MovieClip instance. You could add properties to a movie clip that cause it
          to become an event broadcaster (see the AsBroadcaster class in the
          ActionScript Language Reference and the EventDispatcher class in the
          Components Language Reference).

          > And what is the MovieClipLoader class specifically?

          MovieClipLoader is a non-visual object (like an Array instance, Date
          instance, etc.) that loads external SWFs and other media.

          > Does it "exist" on the stage, or is it just an intermediary
          > that then uses a MovieClip?

          It doesn't use a MovieClip at all. It exists in memory, but it isn't
          visual, so I suppose it doesn't "exist on the Stage" in the way that movie
          clips, buttons, and text fields do.

          > Does it HAVE to be used with the listener object?

          I think so.

          > MovieClips have onLoad() and getBytesLoaded()
          > functions as well...couldn't these be used just as easily
          > to load external content?

          Functions that belong to a given class, such as
          MovieClip.getBytesLoaded(), are called methods. Just like variables that
          belong to a given class are called properties.

          You can certainly use a combo of MovieClip.getBytesLoaded() and
          MovieClip.getBytesTotal() to determine when external content has loaded. In
          fact, this was the way it was done before MovieClipLoader entered the
          picture (back in Flash MX [aka Flash 6] and earlier).

          Check out this recent blog entry of mine for details on this older
          approach to loading content.

          http://www.quip.net/blog/2006/flash/how-to-tell-when-external-swf-loaded

          And you may want to read my article on objects to get a better feel for
          how they're related to classes in ActionScript.

          http://www.quip.net/blog/2006/flash/actionscript-20/ojects-building-blocks

          Hope those help!


          David
          stiller (at) quip (dot) net
          Dev essays: http://www.quip.net/blog/
          "Luck is the residue of good design."


          • 2. Re: Using Listener Objects
            l_andrew_l Level 1
            David,

            I had my fingers crossed that someone would answer each one of my questions step-by-step (numerous though they were). Your explanation was great - simple enough to remain understandable, but not terribly "dumbed down". Thanks!

            quote:

            The MovieClip class does not feature an addListener() method, so I'm a
            bit confused by what you're saying, here.


            I'll start with this since that one statement pretty much shot down 3 of my other questions at once. For the moment, let's set aside custom broadcasting with ASBroacaster and Delegate or what not. So a MovieClip can't be a broadcaster, since it doesn't even have an addListener() method, right? Flash documentation says that "The following ActionScript classes can broadcast events: Key, Mouse, MovieClipLoader, Selection, Stage, and TextField." So these are the classes that are intended to be used with listeners, correct?

            quote:

            [MovieClipLoader] doesn't use a MovieClip at all.


            I think my biggest point of confusion here was whether the MovieClipLoader is ALSO the MovieClip that "contains" the loaded movie, or if it just references ANOTHER MovieClip that will be the container. I'm assuming the latter - "referencing" a MovieClip was what I meant by the word "using".


            Now, switching gears, I have read about "add EventListener" ... but from what I can tell, this is only used with components, is that correct?

            Also, is EventDispatcher only used with components?
            Is it simply a "component oriented" version of ASBroadcaster? Because the more I read about ASBroadcaster and EventDispatcher, the more the line gets blurred for me.

            As I understand it, ASBroadcaster would be used to broadcast "non-standard" events to a listener object. Non-standard meaning something YOU specify, rather than onLoadInit, onProgress, and etc.

            I am currently working on a project that includes "translating text". I will have 'settings' for which language the user wants, and when he changes settings, the language will change. However, depending on which area he is in, the text will "translate" in different ways. For example, for a text field, it will simply swap out one language for another, but I want a menu item to translate in an animated way when the language setting is changed. As I was learning about Listeners, it occurred to me that this might be a perfect job for a special ASBroadcaster. I could use a listener to have each of these objects (the menu, the text field, etc) listen to the language buttons, and when they are changed it would tell them to perform their translation in whichever way they want. Does this make sense, or is a Broadcaster/Listener a bad choice here?


            Andrew
            • 3. Re: Using Listener Objects
              Level 7
              Andrew,

              > For the moment, let's set aside custom broadcasting
              > with ASBroacaster and Delegate or what not. So a
              > MovieClip can't be a broadcaster, since it doesn't
              > even have an addListener() method, right?

              That's a hard one to answer, because you're saying set aside
              ASBroadcaster and EventDispatcher. But that's fine. If we set aside
              those and if by "broadcaster" you mean "an object that requires an event
              listener," then sure, MovieClips aren't broadcasters. I suspect you may be
              getting caught on words, rather than letting the *concept* work its way into
              your understanding.

              > Flash documentation says that "The following
              > ActionScript classes can broadcast events: Key,
              > Mouse, MovieClipLoader, Selection, Stage, and
              > TextField." So these are the classes that are
              > intended to be used with listeners, correct?

              Sure, yes. You can certainly write your own classes -- and if you
              choose, your own classes can broadcast events in the same way -- but for the
              time being, yes, those are the events that require listeners.

              > I think my biggest point of confusion here was whether
              > the MovieClipLoader is ALSO the MovieClip that
              > "contains" the loaded movie, or if it just references
              > ANOTHER MovieClip that will be the container.

              MovieClipLoader is *not* a movie clip. MovieClipLoader is a
              facilitator. Think of it as a shuttle bus at the airport that takes you
              from the parking lot to the plane: it shuttles SWFs, JPGs, etc., from a
              server folder to the SWF.

              > Now, switching gears, I have read about "addEventListener"
              > ... but from what I can tell, this is only used with components,
              > is that correct?

              I can't say for absolute certain, but I think that's right. But from a
              standpoint of simply using it, it works the same way as addListener().
              Frankly, I wish they had the same name.

              > Also, is EventDispatcher only used with components?
              > Is it simply a "component oriented" version of ASBroadcaster?

              To be honest, I haven't used ASBroadcaster yet myself. I use
              EventDispatcher all the time for my own classes, which aren't Components.
              So I can tell you from experience that you may use EventDispatcher for your
              own classes. It may *happen* to be used exclusively with Components that
              are built-in, but it's just another tool in your ActionScript toolbox.

              > Because the more I read about ASBroadcaster and
              > EventDispatcher, the more the line gets blurred for me.

              I think, conceptually, they amount to the same thing.

              > As I understand it, ASBroadcaster would be used to
              > broadcast "non-standard" events to a listener object.
              > Non-standard meaning something YOU specify, rather
              > than onLoadInit, onProgress, and etc.

              I believe that's right. And that's all EventDispatcher does, too.

              > I could use a listener to have each of these objects (the menu,
              > the text field, etc) listen to the language buttons, and when
              > they are changed it would tell them to perform their translation
              > in whichever way they want.

              If these changes are supposed to happen at the click of a button, I
              would just use the existing Button events -- which means event handlers (not
              listeners). Maybe I misunderstand what you're after, but it doesn't make
              sense to me to add custom events to a button if the buttons are simply going
              to do what normal buttons do.

              If it helps put things in perspective ... I wrote a game recently where
              one of my classes, Foe, represented a "villain" object. My Foe class
              inherited from my Avatar class. I also wrote a Friend class that inherited
              from Avatar.

              Avatar describes things that both Friend and Foe have in common: they
              both move, they both have a health rating, etc. So Avatar describes those
              properties, methods, and events. One of the events is Avatar.onCollide,
              which occurs when an Avatar instance collides with another Avatar, a weapon
              of some kind (like a bullet), or a wall.

              Since both Friend and Foe inherit Avatar, both Friend and Foe inherit
              that onCollide event. I used EventDispatcher for that. That's not a
              "normal" event, like a button click. That's an event that has no built-in
              equivalent, so in order to use an event like that, I had to write it.


              David
              stiller (at) quip (dot) net
              Dev essays: http://www.quip.net/blog/
              "Luck is the residue of good design."


              • 4. Re: Using Listener Objects
                l_andrew_l Level 1
                Cool...it's all starting to come into place.

                I don't think I really have enough understanding of classes to start writing my own...the things I'm trying to do at the moment don't really seem to require them either. As a matter of fact my curiosity about listeners sort of LEAD to reading about classes and trying to get a handle on OOP from its basics.

                The thing about the menu is... I do want the buttons to work like normal buttons, but depending on what section of the SWF file (the main menu...or an area with a lot of text), I want it to work in different ways. If it's a menu, I want the text to animate, and if it's a TextField, I just want it to swap the text out. I was assuming that I would just have the buttons on the stage throughout everything in one layer, but if that were the case and I just used standard button handlers, I would be telling the menu to move when it's not even there... I guess there wouldn't be a problem with that but listeners sort seemed like they might be better form.

                On the other hand now that I think about it maybe it would be even BETTER form to have the buttons with normal handlers, but differently coded....as in having AS code replace the buttons' handler code each time they reach that 'section'.... what do you think?

                At any rate, though, you've really helped me clear up those concepts in my mind.

                Thanks a bunch!


                • 5. Re: Using Listener Objects
                  Level 7
                  Andrew,

                  > I don't think I really have enough understanding of
                  > classes to start writing my own...the things I'm trying
                  > to do at the moment don't really seem to require
                  > them either.

                  When you're ready to take the plunge, read through Joey Lott's excellent
                  three-part ActionScript 2.0 Primer ...

                  http://www.person13.com/articles/

                  > I do want the buttons to work like normal buttons, but
                  > depending on what section of the SWF file (the main
                  > menu...or an area with a lot of text), I want it to work
                  > in different ways.

                  Okay.

                  > If it's a menu, I want the text to animate, and if it's a
                  > TextField, I just want it to swap the text out.

                  You might want to write a function, then, that accepts among its
                  parameters a notification of what area the SWF is in.

                  function myFunction(textContent:String, swfArea:String):Void {
                  switch (swfArea) {
                  case "menu":
                  // do a menu thing
                  break;
                  case "text field":
                  // do a text field thing
                  break;
                  // etc.
                  }
                  }

                  > I was assuming that I would just have the buttons
                  > on the stage throughout everything in one layer,
                  > but if that were the case and I just used standard
                  > button handlers, I would be telling the menu to
                  > move when it's not even there...

                  That depends entirely on how you write the function assigned to the
                  button, right?

                  > I guess there wouldn't be a problem with that but
                  > listeners sort seemed like they might be better form.

                  Six of one, half a dozen of the other. In any case, what would your
                  listeners be listening *for*? A button click is a button click ... it's
                  comprised of the mouse clicking down, then releasing. How would a button
                  click be different over a menu from a text field? What event would you have
                  your objects raise? If you're going to use listeners here, you'll probably
                  have to write classes that raise these events.

                  > On the other hand now that I think about it maybe
                  > it would be even BETTER form to have the buttons
                  > with normal handlers, but differently coded....

                  I'm thinking so, too.

                  > as in having AS code replace the buttons' handler code
                  > each time they reach that 'section'.... what do you think?

                  Sure, would work. Of course, if you're going to have ActionScript
                  re-assigning button code anyway, why not have that same code change a global
                  variable?

                  // frame 1
                  _global.swfArea = "";

                  // later ...
                  swfArea = "menu";

                  // button handler at all times (never changes)
                  myButton.onRelease = function() {
                  switch (swfArea) {
                  case "menu":
                  // do a menu thing
                  break;
                  case "text field":
                  // do a text field thing
                  break;
                  // etc.
                  }
                  }

                  > At any rate, though, you've really helped me clear up
                  > those concepts in my mind.

                  Glad to hear that. Have fun with it!


                  David
                  stiller (at) quip (dot) net
                  Dev essays: http://www.quip.net/blog/
                  "Luck is the residue of good design."


                  • 6. Re: Using Listener Objects
                    l_andrew_l Level 1
                    Yep....that makes total sense to me.

                    I'm definitely going to go with a single variable for the "area".
                    I don't know why I never thought of that myself.... but ah, such is programming for me.
                    Hopefully I'll arrive at that answer sooner next time.

                    Anyway, thanks for the help.

                    Andrew