7 Replies Latest reply on Jun 5, 2011 7:35 AM by pauland

    How to make it STOP!

    William Spence

      Got a little mind bender here on program flow.  I am trying to create a lot of thumbnail images from files that a user chooses to upload, allowing them to choose to upload multiple photos at a time.  I am creating thumbnails and putting them into an array that is displayed for the user.  Here is how the files are selected:

       

       

       

      private function importHandler(event:MouseEvent):void{

           var file:File = File.applicationDirectory;

           file.browseForOpenMultiple("Select Files To Import", [acceptableTypes]);

           file.addEventListener(FileListEvent.SELECT_MULTIPLE, mediaSelectHandler);

      }

       

       

       

      The Event Listener listens for multiple file selections and puts them in a FileListEvent.  Cool.  So far so good.  Now, I need to set up a loop to go through each of the files selected and create thumbnails and populate my array.  I do this in a function called "mediaSelectHandler", and the actual thumbnails are made in a function called "resizeImage".

       

       

       

       

      private function mediaSelectHandler(event:FileListEvent):void{


       

           for (var i:int = FILE_COUNT; i < imageArray.length; i++){

       

                var uploadedImage:Image = new Image();

                uploadedImage.load(event.files[i].nativePath);

                uploadedImage.addEventListener(Event.COMPLETE, function(e:Event):void{returnedImage = resizeImage(e,75,75,"crop")});

                imageArray[i] = new Image();

                imageArray[i] = returnedImage; <--- Here is the problem

           }

      }

       

       

       

      Hopefully you can see the problem.  I have added an event listener that listens for my image to complete its upload, and then it calls the function "resizeImage" to make the thumbnail.  The problem is that it does not wait until the thumbnail is created to try and populate the imageArray. So when the image is completed, the thumbnail function is called, but by this time it has already put an empty image into the array.  Is there any way to make the program "pause"(for lack of a better term) until the "resizeImage" fuction has completed before it continues through the "for" loop???

       

      Thanks for any thoughts (not interested in timers, I don't want the user to have to wait forever and there is too much variation between user's machines)

        • 1. Re: How to make it STOP!
          pauland Level 4

          Hi WIlliam,

           

          You need to use a custom event to notify when the the thumbnail processing is complete and take the code that adds the processed thumbnail out of the loop and put it into the event handler for your custom event.

           

          I would avoid using inline functions for event handlers - there is no way to remove the listener afterwards and so memory will leak.

           

          It would look something like this:

           

          private var _imageIdx:uint;_

          private function mediaSelectHandler(event:FileListEvent):void{

               addEventListener("IMAGE_RESIZED", _imageResizedHandler);

               _imageIdx = 0;

              processImage(_imageIdx);

          }

           

          private function _processImage(imageNo:uint):void{

           

          var uploadedImage:Image = new Image();

                    uploadedImage.load(event.files[imageNo].nativePath);

                    uploadedImage.addEventListener(Event.COMPLETE, function(e:Event):void{returnedImage = resizeImage(e,75,75,"crop");

                              dispatchEvent(new Event("IMAGE_RESIZED"));

                    });

          }

           

          private function _imageResizedHandler(e:Event):void{

               imageArray[_imageIdx] = new Image();

               imageArray[_imageIdx] = returnedImage;

               _imageIdx++;

               if (_imageIdx < imageArray.length){

                    _processImage(_imageIdx);

               } else {

                    removeEventListener("IMAGE_RESIZED", _imageResizedHandler);

                    // all images processed

               }

          }

           

           

          Naturally, this code is untested..

           

          Paul

          • 2. Re: How to make it STOP!
            William Spence Level 1

            Wow Paul, I can see you have delt with these kind of issues before.  I figured I needed to dispatch a custom event, I just couldnt figure out how to do this without a For loop. I can't thank you enough for taking the time to post, you saved me a big headache and a lot of time.

            • 3. Re: How to make it STOP!
              Brian Vaughn Level 1

              I would avoid using inline functions for event handlers - there is no way to remove the listener afterwards and so memory will leak.

               

               

              Actually...

               

              var ed:EventDispatcher = new EventDispatcher();
              ed.addEventListener( "foobar",
                   function( e:Event ):void {
                        ed.removeEventListener( "foobar", arguments.callee );
                   } );
              
              

               

              Docs about the "callee" attribute here:

              http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/arguments.html

              • 4. Re: How to make it STOP!
                pauland Level 4

                Good post Brian. Thanks.

                • 5. Re: How to make it STOP!
                  pauland Level 4

                  William Spence wrote:

                   

                  Wow Paul, I can see you have delt with these kind of issues before.  I figured I needed to dispatch a custom event, I just couldnt figure out how to do this without a For loop. I can't thank you enough for taking the time to post, you saved me a big headache and a lot of time.

                   

                  LOL, yes, I've hit this problem before. Just remember I've just written that stuff on the fly - it may need some debugging.

                   

                  Thanks for the kind comments and good luck!

                   

                  [ edit: The line in the handler that says " imageArray[_imageIdx] = new Image();"  shouldn't be there  ]

                  • 6. Re: How to make it STOP!
                    William Spence Level 1

                    Paul, do you know how to put images into an arrayCollection using actionscript? Because the images that I am using are created dynamically, I need to do all of this in actionscript. I want to use an arrayCollection of images as a data provider for a tileList, but just can't seem to get the images to display. Sorry, I am a Flex newbie and you see to know your way around the ring pretty well. Thanks for any help you can offer.

                    • 7. Re: How to make it STOP!
                      pauland Level 4

                      As per the other thread - the default Image item renderer wants paths not images:

                       

                      <?xml version="1.0" encoding="utf-8"?>
                      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
                      <mx:Script>
                          <![CDATA[
                           import mx.collections.ArrayCollection;
                           [Bindable]
                           private var _filePaths:ArrayCollection = new ArrayCollection(
                           ["http://www.xara.com/theme/xtreme5/xaralogo.png",
                                       "http://www.xara.com/uploaded_files/2011/3/23/GSCJnMzT/wd7.jpg"]);

                          ]]>
                      </mx:Script>
                          <mx:TileList dataProvider="{_filePaths}"  itemRenderer="mx.controls.Image"/>
                      </mx:Application>