0

我正在开发一个 Flex Air(桌面)应用程序,它将图像从本地文件系统加载到 TileList 中。然后,用户将能够将这些图像从列表中拖出(复制)到另一个控件上。

我终于让图像正确显示(并且在滚动 TileList 后不会消失),但它们似乎在拖动操作开始时从 TileList 中消失。

我来自 .NET 背景,正在学习 AS3/Flex,所以如果你看到我在这里使用了任何反模式,请随时指出它们!

示例代码如下(我已尝试使其尽可能小)。


测试.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>


图片对象.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;
        }
    }
}
4

2 回答 2

1

我将主要回答您的次要问题(猜测它会一举解决主要问题):随着反模式的发展,这不是一个坏例子;)

  1. 您正在手动加载图像,而Image该类具有内置的加载功能;只需为其source属性提供一个 URL,它就会自动加载它。
  2. 您正在将一个Image实例设置为另一个Image实例的源;该source属性需要 URL 或 ByteArrays;我很惊讶它没有抛出错误;Image 类可能足够聪明,可以提取source另一个 Image 实例的。
  3. Timer是多余的。如前所述, anImage会自动处理加载其内容。
  4. s:Image标记没有包装在 an 中,ItemRenderer因此不应访问data属性:此代码甚至不应该编译。
  5. 如果你不打算绑定它,那么拥有一个Bindable属性是没有意义的。_pics
  6. 您使用 mx TileList。为什么不使用更“现代”的 Spark 版本?(但这并不意味着 mx 类不能在 Spark 应用程序中工作)。

所以你有很多删除工作要做。您可以完全废弃 PictureObject 类;删除定时器代码;并将 URL 字符串添加到_pics集合中。另外,您还可以将 mx TileList 替换为带有 TileLayout 的 Spark 列表;像这样的东西:

<s:List id="picsList">
    <s:layout>
        <s:TileLayout />
    </s:layout>
    <s:itemRenderer>
        <fx:Component>
            <s:ItemRenderer>
                <s:Image source="{data}" />
            </s:ItemRenderer>
        </fx:Component>
    </s:itemRenderer>
</s:List>

ActionScript 部分可以简化为:

const imageFolderPath:String = "c:\\users\\bbrooks\\Pictures";

var imageDir:File = new File(imageFolderPath);
var imageFiles:Array = imageDir.getDirectoryListing();
picsList.dataProvider = new ArrayCollection(imageFiles);
于 2012-05-11T22:35:53.073 回答
0

谢谢RIAstar。您的回答使我走上了解决问题的道路。新的示例代码如下所示。

最初的问题似乎与 mx:Image 控件有关。不知道为什么,但使用 s:Image 控件似乎有效。

当然,这可以通过简单地将数据源设置为文件路径列表来完成,而无需 PictureObject 类,但我稍后会使用图像数据,我想通过将图像数据提供给自定义渲染器来使其工作动态的。

测试.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;

            import spark.components.Image;

            protected var _pics:ArrayCollection = new ArrayCollection();

            protected function picsList_creationCompleteHandler(event:FlexEvent):void
            {
                const imageFolderPath:String = "c:\\users\\bbbrooks\\Pictures";

                var imageDir:File = new File(imageFolderPath);
                var imageFiles:Array = imageDir.getDirectoryListing();
                for each(var imageFile:File in imageFiles)
                {
                    if (imageFile.extension == "jpg")
                    {
                        _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>

    <s:List id="picsList" x="0" y="0" width="100%" height="100%" 
            creationComplete="picsList_creationCompleteHandler(event)"
            dragEnabled="true" dragMoveEnabled="false">
        <s:layout>
            <s:TileLayout />
        </s:layout>
        <s:itemRenderer>
            <fx:Component>
                <s:ItemRenderer>
                    <s:Image id="imageDisplay" 
                             width="75" height="75" source="{data.bmp}" /> 
                </s:ItemRenderer>
            </fx:Component>
        </s:itemRenderer>
    </s:List>

</s:WindowedApplication>


图片对象.as

package
{
    import flash.display.Bitmap;
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.events.Event;
    import flash.net.URLRequest;

    import mx.controls.Image;

    [RemoteClass]
    [Bindable]
    public class PictureObject extends Object
    {
        protected var _bmp:Bitmap = null;
        public function get bmp():Bitmap { return _bmp; }
        public function set bmp(newValue:Bitmap):void { _bmp = 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;

            // create our own copy of the bits in the Loader
            var bmp:Bitmap = Bitmap(imageLoader.content);
            _bmp = new Bitmap( Bitmap(imageLoader.content).bitmapData );
        }
    }
}
于 2012-05-14T21:04:56.760 回答