2011-07-12 5 views
1

基本的に1メートル(スキン可能なコンテナを拡張)のコンポーネントを作成しました。コンポーネントのスキンには、2つの長方形(背景と実際のメーター)が含まれています。このコンポーネントは、次のフィールドvalue、max、minを持つ配列コレクションを受け取ります(渡す配列のコレクションはBindableです)。描画に使用するデータを初期化して渡すときにはうまくいきます(頭に入れておいてください)。データ配列を変更し、現在のメーター値を表示するボタンを作成しました。明らかに、私がレンダリングに使用するように設定したArrayCollectionを変更するたびに、メーターの値が変更されています。(Flexデータプロバイダではなく、単に変数であるため、「dataProvider」とは言いません...) 。カスタムコンポーネントが表示リストを更新していません

public class meter extends SkinnableContainer { 


    [SkinPart(required = "true")] 
    public var meter:spark.primitives.Rect; 

    [SkinPart(required = "true")] 
    public var meterBackground:spark.primitives.Rect; 

    private var _dataProvider:ArrayCollection; 
    private var _renderDirty:Boolean = false; 

    public function Meter() { 
     super(); 
    } 

    public function set dataProvider(value:Object):void { 
     if (value) 
     { 
      if(value is ArrayCollection) 
       { 
        _renderDirty = true; 
       _dataProvider = value as ArrayCollection; 
       }     
      if(_dataProvider) 
      { 
       _dataProvider.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, propertyChanged);//used both eventlisteners but none actually ever fire off 
       _dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE,collectionChanged); 
      } 
      invalidateDisplayList();//only happens the first time 
     } 
    } 

    private function collectionChanged(event:CollectionEvent):void 
    { 
     Alert.show("In collection Change");//this never goes off when I change the "dataProvider" 
     _renderDirty = true; 
     invalidateDisplayList(); 
    } 

    private function propertyChanged(event:PropertyChangeEvent):void 
    { 
     Alert.show("In property Change");//this never goes off when I change the "dataProvider" 
     _renderDirty=true; 
     invalidateDisplayList(); 
    } 

    public function get dataProvider():Object { 
     return _dataProvider; 
    }   

    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { 


     if(_dataProvider)) 
     { 
     var span:Number = unscaledWidth/_dataProvider[0].max; 
     var meterWidth:Number = _dataProvider[0].value * span; 

     meter.width = meterWidth; 
     _renderDirty = false; 
     } 

    } 

そして、これは私が「値」フィールドを変更するMXMLコードです....

<fx:Script> 
    <![CDATA[ 
    [Bindable] 
     private var meterData:ArrayCollection = new ArrayCollection([     
      {value:80, max:100, min:0} 
     ]); 

     protected function mySlider_changeHandler(event:Event):void 
     { 
      meterData[0].value = Math.round(mySlider.value)*10;     
     } 

     protected function button1_clickHandler(event:MouseEvent):void 
     { 
      // TODO Auto-generated method stub 
      var array:ArrayCollection = testMeter.dataProvider as ArrayCollection; 
      var value:Number = array[0].value as Number; 
      Alert.show(value.toString()); 
      // testMeter.meter.width= Math.random()*100; 
     } 

    ]]>//initial value in "meterData" does get drawn...but when it's changed with the slider..nothing happens.. 

    <custom:Meter id="testMeter" dataProvider="{meterData}" /> 
    <s:HSlider id="mySlider" 
       liveDragging="true" 
       dataTipPrecision="0" 
       change="mySlider_changeHandler(event)" 
       value="3"/> 
    <s:Button click="button1_clickHandler(event)"/> 

は、あなたは私がみんなありがとう??に何が起こっているかを把握助けることができます!

+0

これは答えではありませんが、最近私は概念の証明として同様のコンポーネントを作成しました:http://www.jeffryhouser.com/index.cfm/2011/6/26/How-do-you-create -a-Status-Bar-in-Flexさまざまなアプローチで楽しむことができます。 :-) – JeffryHouser

答えて

3

問題は、dataProviderをリセットしておらず、collectionChangeイベントを発生させないことです。私はそれぞれ個々に対処します。ここでdataProviderをリセットする方法は次のとおりです。

testMeter.dataProvider = newDataPRovider; 

しかし、あなたはそうしていません。したがって、setメソッドは、最初の初期セットの後に決して実行されません。

collectionChangeイベントが発生する必要がある場合は、コレクションを変更する必要があります。あなたは実際にそれをやっていません。コレクション内のオブジェクトを変更しています。

meterData[0].value = Math.round(mySlider.value)*10; 

それはちょうど、コレクションの目的の一つで単一のプロパティを変更します。このコードは、コレクションを変更しません。

var newObject = meterData[0]; 
newObject['value'] = Math.round(mySlider.value)*10 
meterData.addItem(newObject); 

このコードでは、コードはありませんが、colletionChangeイベントは発生しません。

私の主な質問とは無関係に、もう少し考えがあります。このように、dataProviderのセット方法でremoveEventListenersに必ず:

public function set dataProvider(value:Object):void { 
    if (value) 
    { 
// remove the event listeners here before changing the value 
// that should allow the object to have no extra 'references' that prevent it from being garbage collected 
       _dataProvider.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, propertyChanged); 
       _dataProvider.removeEventListener(CollectionEvent.COLLECTION_CHANGE,collectionChanged); 

      if(value is ArrayCollection) 
       { 
        _renderDirty = true; 
       _dataProvider = value as ArrayCollection; 
       }     
      if(_dataProvider) 
      { 
       _dataProvider.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, propertyChanged);//used both eventlisteners but none actually ever fire off 
       _dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE,collectionChanged); 
      } 
      invalidateDisplayList();//only happens the first time 
     } 
    } 

そして、あなたが言った:

(それは、ちょうど変数フレックス データプロバイダではありませんので、「dataProviderのを」言いたいいけません)

フレックスリストのDataProvider、またはDataGrid、またはDataGroupも「単なる変数」です。とにかく、「Flex Framework」の実装が、あなたがやったこととはまったく異なっていることはわかりません。おそらく最小値と最大値を想定しているので、ArrayCollectionではなく明示的なプロパティを持つValueオブジェクトを使用してください。

+0

ありがとうLOT !!!! – Joe

+0

うれしかった! – JeffryHouser

+0

だから、それは配列ではなかったコレクションは、オブジェクトが??それが変更されたかどうかはどうすればわかりますか? – Joe

関連する問題