为什么我得到这个“无法访问空对象引用的属性或方法”错误?

时间:2010-09-06 17:25:37

标签: flex actionscript

我是flex和actionscript的新手。我正在尝试创建一个具有多个状态的小型flex应用程序,但是如果我有嵌套容器,看起来有些对象在我预期的时候没有被初始化,即使我将creationPolicy设置为“all” 。“

我已将问题简化为一个小例子,其中一个注释块显示 的工作时间。

使用现有代码,我收到此错误:“TypeError:错误#1009:无法访问main / 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>

感谢您的反馈。

3 个答案:

答案 0 :(得分: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>

如果您不喜欢这样,请将Button切换到自定义组件基于Panel with VBox和Button,这样您就可以将其重写为几乎与注释代码相似,但您将使用容器。

如果我们回答问题为什么关于访问的奇怪内容会成真

因为您使用了3个容器:Panel VBox和Button,并且在面板完成后完成了对应用程序/创建完成的事件 - 完成,而不是其子项。

清除?

答案 1 :(得分:0)

  1. 我认为该商家位于applicationComplete活动中,请使用creationComplete instead
  2. 在您的代码中,您说评论代码在addChild中有效,因为它没有双容器,如在未注释的代码中,例如Panel内部的Button Inside VBox。
  3. 最后,我的建议是:请保留所有旧的flex版本,并迁移到Flex 4 Gumbo,因为它具有很好的states逻辑。
  4. 最诚挚的问候 尤金

答案 2 :(得分: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>