I'm developing a Flex Air (desktop) application that loads images from the local filesystem into a TileList. The user will then be able to drag (copy) these images out of the list onto another control.
I've finally got the images showing up correctly (and not disappearing after scrolling the TileList) but they seem to disappear from the TileList at the start of a drag operation.
I come from a .NET background and am just learning AS3/Flex, so if you see me using any anti-patterns here, feel free to point them out!
Sample code follows (I've tried to make this as minimal as possible).
Test.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
[Bindable]
protected var _pics:ArrayCollection = new ArrayCollection();
protected function picsList_creationCompleteHandler(event:FlexEvent):void
{
const imageFolderPath:String = "c:\\users\\bbrooks\\Pictures";
var imageDir:File = new File(imageFolderPath);
var imageFiles:Array = imageDir.getDirectoryListing();
for each(var imageFile:File in imageFiles)
{
_pics.addItem(new PictureObject(imageFile.nativePath));
}
// give images a chance to load
var timer:Timer = new Timer(1000);
timer.addEventListener(TimerEvent.TIMER, onTimerExpired);
timer.start();
}
protected function onTimerExpired(event:TimerEvent):void
{
picsList.dataProvider = _pics;
}
]]>
</fx:Script>
<mx:TileList id="picsList" x="0" y="0" width="100%" height="100%" dragEnabled="true" dragMoveEnabled="false"
creationComplete="picsList_creationCompleteHandler(event)" >
<mx:itemRenderer>
<fx:Component>
<mx:Image width="75" height="75" source="{data.image}" />
</fx:Component>
</mx:itemRenderer>
</mx:TileList>
</s:WindowedApplication>
PictureObject.as:
package
{
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.Event;
import flash.net.URLRequest;
import mx.controls.Image;
[Bindable]
[RemoteClass]
public class PictureObject extends Object
{
protected var _image:Image = null;
public function get image():Image { return _image; }
public function set image(newValue:Image):void { _image = newValue; }
public function PictureObject(path:String)
{
var imageLoader:Loader = new Loader();
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
imageLoader.load(new URLRequest(path));
}
protected function onImageLoaded(e:Event):void
{
var imageLoader:Loader = LoaderInfo(e.target).loader;
var bmp:Bitmap = Bitmap(imageLoader.content);
_image = new Image();
_image.smoothBitmapContent = true;
_image.source = new Bitmap(bmp.bitmapData);
_image.width = imageLoader.width;
_image.height = imageLoader.height;
}
}
}
I will mostly reply to your secondary question (guessing it will resolve the primary in one fell swoop): as anti-patterns go, this is not a bad example ;)
Imageclass has the loading built-in; just give a URL to itssourceproperty and it will automatically load it.Imageinstance as the source of anotherImageinstance; thesourceproperty expects URLs or ByteArrays; I'm surprised it doesn't throw an error; the Image class is probably smart enough to extract thesourceof the other Image instance.Timeris redundant. As said, anImageautomatically takes care of loading its content.s:Imagetag isn't wrapped in anItemRendererand hence should have no access to adataproperty: this code shouldn't even compile.Bindableproperty_picsif you don't plan on binding it.So you have a lot of deleting to do. You can scrap the PictureObject class altogether; remove the Timer code; and just add the URL Strings to the
_picscollection. As a plus you could also replace the mx TileList with a Spark List with TileLayout; something like this:The ActionScript part could be reduced to this: