Почему я получаю эту ошибку «Не удается получить доступ к свойству или методу пустой ссылки на объект»? - PullRequest
2 голосов
/ 06 сентября 2010

Я новичок в flex и actioncript.Я пытаюсь создать небольшое гибкое приложение с несколькими состояниями, но если у меня есть вложенные контейнеры, похоже, что некоторые объекты не инициализируются, когда я ожидал, что они будут, даже когда для creationPolicy установлено значение "all". "

Я уменьшил проблему до небольшого примера с закомментированным блоком, показывающим, когда работает .

Используя существующий код, я получаю эту ошибку: «TypeError: Ошибка # 1009: невозможно получить доступ к свойству или методу пустой ссылки на объект в main / init ()», и обработчики событий не установлены.

Если я вместо этого использую закомментированный блок, которыйУдалены элементы Panel и VBox, работает .

Я знаю, что могу добавить атрибут click к элементам mxml, но это всего лишь упрощенный пример, и меня больше интересуетзная, почему объекты не инициализируются при загрузке приложения.

<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 ]

2 голосов
/ 07 сентября 2010

Что делать, если вы сделаете следующее:

 <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 с VBox и Button, чтобы вы переписали его почти как закомментированный код, но вы будете использовать контейнеры.

И если мы ответим на вопрос Почему этот странный материал о доступе сбывается :

, потому что вы используете 3 контейнера: Panel VBoxи Button, и события, отправляющие все, выполняются для application / creation-Complete после завершения панели only , а не ее дочерних элементов.

Clear?

0 голосов
/ 07 сентября 2010

Поскольку атрибут creationPolicy = "all" не работает так, как я думал, для сложных изменений состояния я установил метод инициализации состояния для каждого состояния, отключенный от события currentStateChange. Вот пример того, что я сделал, включая обновление для использования состояний Flex 4, хотя в этом примере я не использую искровые компоненты.

<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 голосов
/ 06 сентября 2010
  1. Я думаю, что дело в applicationComplete , используйте creationComplete вместо .
  2. В своем коде вы сказали, что закомментированный код работает в addChild , потому что он не имеет двойных контейнеров, как в некомментированном коде, например Button Inside VBox внутри Panel.
  3. И, наконец, мой совет: пожалуйста, оставьте все старые версии Flex и перейдите на Flex 4 Gumbo, потому что он имеет отличную состояния логику.

С наилучшими пожеланиями
Евгений

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...