2012-05-11 59 views
0

我正在開發一個Flex Air(桌面)應用程序,用於將本地文件系統中的圖像加載到TileList中。用戶將能夠將這些圖像從列表中拖出(複製)到另一個控件上。Flex:爲什麼TileList圖像在拖動時消失?

我終於得到正確顯示的圖像(並且在滾動TileList之後沒有消失),但它們似乎在拖動操作開始時從TileList中消失。

我來自.NET的背景,只是學習AS3/Flex,所以如果你看到我在這裏使用任何反模式,隨時指出它們!

示例代碼如下(我儘量使其儘可能最小)。


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; 
     } 
    } 
} 

回答

1

我將主要回答你的問題,二級(猜它會解決的首要的一舉一動):如反模式一樣,這不是一個壞例子;)

  1. 您正在手動加載圖像,而Image類具有內置加載;只需提供一個到其source屬性的網址,它就會自動加載它。
  2. 您正在設置一個Image實例作爲另一個Image實例的源; source屬性需要URL或ByteArrays;我很驚訝它不會拋出一個錯誤; Image類可能足夠聰明以提取其他Image實例的source
  3. Timer是多餘的。如上所述,Image會自動負責加載其內容。
  4. s:Image標記未包含在ItemRenderer中,因此應該無法訪問data屬性:此代碼甚至不應編譯。
  5. 如果您不打算對其進行綁定,則無需Bindable屬性_pics
  6. 您使用mx TileList。爲什麼不使用更「現代」的Spark版本? (這並不意味着mx類在Spark應用程序中不起作用)。

所以你有很多刪除操作。您可以完全取消PictureObject類;刪除定時器代碼;只需將URL字符串添加到_pics集合中即可。作爲一個加號,你也可以用TileLayout替換Spark列表中的mx TileList;是這樣的:

<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); 
+0

感謝您的答覆!爲了解決您的觀點...(1)我這樣做是爲了解決我遇到的一個問題,即在用戶向前滾動然後滾動回來後圖像不會重新繪製。 (2)這是在準備這個例子時犯的一個錯誤。我已更新示例源以更準確地反映原始代碼。 (4)我使用了一個mx:Image標籤,它被包裝在一個ItemRenderer中。 (5)我不知道s:List有一個tile佈局模式。但是,用s:List替換mx:TileList會導致未繪製圖像。 –

+0

@BillBrooks(1)這不應該發生,所以問題必須在其他地方。更好地跟蹤下來,而不是試圖解決症狀。 (4)我的錯誤:Flex似乎自動用mx List將它包裝在ItemRender中。但這不會與Spark List一起工作:那麼您必須明確地執行此操作。 (5)這可能是因爲你沒有給它寬度或高度。出於某種原因,它不會像VerticalLayout那樣需要最小尺寸。或者嘗試在TileLayout上設置requestedColumnCount或requestedRowCount。 – RIAstar

0

感謝RIAstar。你的回答讓我走上了解決問題的軌道。新的示例代碼如下所示。

最初的問題似乎是與mx:Image控件一起使用。不知道爲什麼,但使用s:Image控件似乎工作。當然,這可以在沒有PictureObject類的情況下完成,只需將數據源設置爲文件路徑列表即可,不過我稍後使用了圖像數據,並且希望通過提供圖像數據來實現它。動態地自定義渲染器。

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; 

      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> 


PictureObject.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); 
     } 
    } 
} 
+0

即使在這種情況下,也不是必須的:您可以通過[Image#bitmapData](http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/components/Image.html)訪問圖像數據#bitmapData)(只讀) – RIAstar

相關問題