2012-05-11 6 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 имеет встроенную загрузку; просто укажите URL-адрес своего свойства source и он автоматически загрузит его.
  2. Вы устанавливаете экземпляр Image в качестве источника другого экземпляра Image; свойство source ожидает URL или ByteArrays; Я удивлен, что это не вызывает ошибки; класс Image, вероятно, достаточно умен, чтобы извлечь source другого экземпляра изображения.
  3. Timer является избыточным. Как сказано, Image автоматически берет на себя загрузку содержимого.
  4. Тег s:Image не обернут в ItemRenderer и, следовательно, не должен иметь никакого доступа к свойству data: этот код даже не компилируется.
  5. Нет смысла иметь Bindable объект _pics, если вы не планируете его привязывать.
  6. Вы используете mx TileList. Почему бы не использовать более «современную» версию Spark? (Это не означает, что класс mx не будет работать в приложении Spark, хотя).

У вас есть много дел, чтобы сделать. Вы можете полностью отказаться от класса PictureObject; удалить код таймера; и просто добавьте URL-строки в коллекцию _pics. В качестве плюса вы также можете заменить mx TileList на Spark List с помощью TileLayout; что-то вроде этого:

<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 имеет режим компоновки плитки. Однако замена mx: TileList на s: List приводит к тому, что изображения не будут рисоваться. –

+0

@BillBrooks (1) Этого не должно быть, поэтому проблема должна быть где-то в другом месте. Лучше отслеживайте это, вместо того, чтобы пытаться исправить симптомы. (4) Моя ошибка: Flex, кажется, автоматически обертывает его в ItemRender с помощью mx List. Это не будет работать с Spark List, хотя: вам придется делать это явно. (5) Это может быть потому, что вы не дали ему ширины или высоты. По какой-то причине он не принимает минимальный размер, как это делает VerticalLayout. Или, возможно, попробуйте установить 'requestColumnCount' или' requestRowCount' в TileLayout. – RIAstar

0

Благодаря RIAstar. Ваш ответ поставил меня на путь решения проблемы. Ниже приведен новый образец кода.

Оригинальная проблема, похоже, была с контролем mx: Image. Не уверен, почему, но использование s: Image control работает.

Конечно, это может быть выполнено без класса 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