2010-09-06 44 views
2

我是新來flex和actionscript。我正在嘗試創建一個具有多個狀態的小型Flex應用程序,但是如果我有嵌套容器,那麼當我預期它們是某些對象時,它們看起來不會被初始化,即使我將creationPolicy設置爲「all 「。爲什麼我得到這個「無法訪問空對象引用的屬性或方法」錯誤?

我已將這個問題簡化爲一個小例子,其中有一個註釋塊顯示它何時確實有效。

使用現有的代碼,我得到此錯誤:「TypeError:錯誤#1009:不能訪問主/ init()空對象引用的屬性或方法」,並且未安裝事件處理程序。

如果我改爲使用註釋塊,其中Panel和VBox元素已被刪除,它確實的工作。

我知道我可以給mxml元素添加一個click屬性,但這只是一個簡化的例子,我更感興趣的是知道爲什麼應用程序加載時未初始化對象。

<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
    applicationComplete="init();" 
    currentState="start"> 

<mx:Script> 
    private function mainButtonHandler(event:Event):void{ 
    currentState = "start" 
    } 

    private function startButtonHandler(event:Event):void { 
    currentState = "main"; 
    } 

    public function init():void{ 
    mainButton.addEventListener(MouseEvent.CLICK, mainButtonHandler); 
    startButton.addEventListener(MouseEvent.CLICK, startButtonHandler); 
    } 
</mx:Script> 

<!-- this does not work --> 
<mx:states> 
    <mx:State name="main"> 
    <mx:AddChild creationPolicy="all"> 
     <mx:Panel creationPolicy="all"> 
     <mx:VBox creationPolicy="all"> 
      <mx:Button id="mainButton" label="Change to Start State"/> 
     </mx:VBox> 
     </mx:Panel> 
    </mx:AddChild> 
    </mx:State> 

    <mx:State name="start"> 
    <mx:AddChild creationPolicy="all"> 
     <mx:Panel creationPolicy="all"> 
     <mx:VBox creationPolicy="all"> 
      <mx:Button id="startButton" label="Change to Main state"/> 
     </mx:VBox> 
     </mx:Panel> 
    </mx:AddChild> 
    </mx:State> 
</mx:states> 

<!-- this works --> 
<!-- 
<mx:states> 
    <mx:State name="main"> 
    <mx:AddChild creationPolicy="all"> 
     <mx:Button id="mainButton" label="Change to Start State"/> 
    </mx:AddChild> 
    </mx:State> 

    <mx:State name="start"> 
    <mx:AddChild creationPolicy="all"> 
     <mx:Button id="startButton" label="Change to Main state"/> 
    </mx:AddChild> 
    </mx:State> 
</mx:states> 
--> 

</mx:Application> 

感謝您的任何反饋。

回答

2

如果你會做下一件事:

<mx:State name="main"> 
     <mx:Panel creationPolicy="all"> 
     <mx:VBox creationPolicy="all"> 
     <mx:AddChild creationPolicy="all"> 
      <mx:Button id="mainButton" label="Change to Start State"/> 
     </mx:AddChild> 
     </mx:VBox> 
     </mx:Panel>  
    </mx:State> 

如果你不喜歡這樣,切換您的按鈕基於面板與垂直框和按鈕自定義組件,所以你會重寫它幾乎像評論代碼,但你會使用一個容器。

如果我們將回答質疑爲什麼有關訪問這個奇怪的東西成爲現實

因爲你用3個容器:面板垂直框和按鈕,調度所有事件做是爲了應用程序/創建完成後, 只有面板完成,不是它的子。

清除?

+0

Eugene,我想我明白了,但是我可以期望(或強制)給定上下文中的所有mxml生成對象,例如狀態,以便初始化嗎?何時可以安全地使用動作腳本來觸摸? – mshiltonj 2010-09-08 11:23:16

+0

一個簡短的壞方法,只是添加創建完整的事件處理程序給每個組件,在其他情況下,我應該研究一下,我會讓你知道的 – Eugene 2010-09-08 14:47:50

0
  1. 我認爲企業是在applicationComplete情況下,使用creationCompleteinstead
  2. 在您的代碼中,您表示註釋代碼在addChild中工作,因爲它沒有雙容器,就像在未註釋的代碼中一樣,例如面板中的Button Inside VBox。
  3. 最後,我的建議是:請保留所有舊的flex版本,並遷移到Flex 4 Gumbo,因爲它具有很好的邏輯邏輯states

問候
尤金

+0

感謝您的幫助。我將閱讀更多關於Flex 4狀態的信息。但是,無論我使用applicationComplete還是creationComplete,我仍然有相同的錯誤。 :-( – mshiltonj 2010-09-06 23:43:54

0

由於creationPolicy =「all」屬性不按照我認爲的方式工作,因此對於複雜的狀態更改,我爲每個狀態設置了一個「狀態初始化」方法,並從currentStateChange事件中鍵入。下面是我所做的一個例子,其中還包括使用Flex 4狀態的更新,儘管在示例中我沒有使用Spark組件。

<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    applicationComplete="init();" 
    currentStateChange="stateChange(event);" 
    creationPolicy="all" 
    currentState="bar" 
    > 

<fx:Script> 
    import mx.controls.Alert; 
    import mx.events.StateChangeEvent; 

    private var InittedStates:Object = new Object(); 

    private function mainButtonHandler(event:Event):void{ 
    currentState = "bar" 
    } 

    private function startButtonHandler(event:Event):void { 
    currentState = "foo"; 
    } 

    public function stateChange(event:StateChangeEvent):void{ 
     if (event.newState === 'bar'){ 
     initBarState(); 
     } 
     else if(event.newState === 'foo'){ 
     initFooState(); 
     } 
    } 

    public function initBarState():void { 
    if (InittedStates.bar){ 
     return; 
    } 
    startButton.addEventListener(MouseEvent.CLICK, startButtonHandler); 
    InittedStates.bar = true; 
    } 

    public function initFooState():void { 
    if (InittedStates.foo){ 
     return; 
    } 
    mainButton.addEventListener(MouseEvent.CLICK, mainButtonHandler); 
    InittedStates.foo = true; 
    } 

    public function init():void{ 
    } 
</fx:Script> 

<s:states> 
    <s:State name="foo"/> 
    <s:State name="bar"/> 
</s:states> 


<mx:Panel includeIn="foo" creationPolicy="all"> 
    <mx:VBox creationPolicy="all"> 
    <mx:Button id="mainButton" label="Change to Start State"/> 
    </mx:VBox> 
</mx:Panel> 

<mx:Panel includeIn="bar" creationPolicy="all"> 
    <mx:VBox creationPolicy="all"> 
    <mx:Button id="startButton" label="Change to Main state"/> 
    </mx:VBox> 
</mx:Panel> 

</s:Application> 
+0

即使這樣也行不通當我在一個狀態中添加一個tab容器時,當狀態改變事件被觸發時,其中一個選項卡中的面板中的對象仍然未被初始化,所以,我仍然不確定(例如)將事件監聽器附加到mxml生成的對象的最佳方式。當我期望所有的物體都準備好時,不要吝嗇,我錯過了什麼? – mshiltonj 2010-09-08 11:20:14

相關問題