0

在 Scroller.as 类第 2139 行中,我收到以下错误:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at spark.components::Scroller/focusInHandler()[E:\dev\4.y\frameworks\projects\spark\src\spark\components\Scroller.as:2139]
    at flash.display::Stage/set focus()

来自 Scroller.as

/**
 *  @private 
 *  Listens for any focusIn events from descendants 
 */ 
override protected function focusInHandler(event:FocusEvent):void
{
    super.focusInHandler(event);

    // When we gain focus, make sure the focused element is visible
    if (viewport && ensureElementIsVisibleForSoftKeyboard)
    {
        var elt:IVisualElement = focusManager.getFocus() as IVisualElement; 
        lastFocusedElement = elt;
    }
}

由于这是框架代码,我有什么选项可以阻止它?

上下文
我创建了一个弹出 TitleWindow,在其中添加了一个 Module 并显示它。Module 有几个 State,每个 State 中是一个 Group,一个 Group 有一个 List,那个 List 有一个 ItemRenderer,那个 ItemRenderer 有一个 Checkbox。

该模块还有一个菜单。打开菜单时,弹出菜单会列出模块可用的状态。当从弹出菜单中选择一个项目时,我会更改为另一种状态。

当状态改变并且最后一项是复选框时,就会产生错误。至少这是我认为正在发生的事情。我推断这是因为在 Scroller 类中,处理程序正在处理一个事件。在那个事件上是当前的目标。当前目标是复选框。

更新- 重现步骤

// inside the Application.mxml
// define variables
public var popup:Group;
public var titleWindow:TitleWindow;


// shows pop up
public function showInspector():void {

    // inside show inspector method
    // create new inspector container
    popup = new InspectorContainer(); // a group implements="mx.managers.IFocusManagerContainer"
    titleWindow = new TitleWindow();
    titleWindow.addElement(popup);

    // display pop up title window
    PopUpManager.addPopUp(titleWindow, this, false);
}

<fx:Declarations>
    <modules:InspectorContainer/>
</fx:Declarations>
  1. 显示弹出。弹出窗口是一个标题窗口,其中 InspectorContainer(一个组)作为第一个元素。

  2. 在弹出窗口从家庭状态(默认状态)更改为在线状态(当用户单击按钮时会发生这种情况)。在线状态有一个列表。List 有一个 itemrenderer。itemrenderer 有一个复选框。选中复选框。到目前为止,一切都很好。

  3. 弹出窗口 (InspectorContainer) 有一个 mx:MenuBar 实例。当您单击菜单栏中的项目时,菜单栏会显示一个菜单项。

  4. 单击菜单列表中的项目。调用 itemClick menuHandler。在此函数中,弹出窗口更改状态。

这是发生错误的时候。

4

3 回答 3

4

错误的主要原因是UIComponent中的get函数“focusManager”:

public function get focusManager():IFocusManager
{
    if (_focusManager)
        return _focusManager;

    var o:DisplayObject = parent;

    while (o)
    {
        if (o is IFocusManagerContainer)
            return IFocusManagerContainer(o).focusManager;

        o = o.parent;
    }

    return null;
}

如下代码,你可以看到uicomponent第一次得到它的focusmanager是从它的parent,parent.parent和parent.parent.parent...错误的); 它的 parent 是 SystemManager,它的 parent.parent 是 Stage,它们要么不是 IFocusManagerContainer,所以要么没有 focusManager 属性,因此结果为 null。

最后我的解决方案是覆盖直接使用组件,如果您需要修复 2 层组件,请将 focusManager 传递给它。

package cn.easymenu.view.components{
 import mx.core.FlexGlobals;
 import mx.managers.IFocusManager;

 import spark.components.TextArea;

 public class TextArea extends spark.components.TextArea{
  override protected function partAdded(partName:String, instance:Object):void{
   super.partAdded(partName, instance);
   if(instance == scroller){
    scroller.focusManager=this.focusManager;
   }
 }

 override public function get focusManager():IFocusManager{
  var ifm:IFocusManager=super.focusManager;
  if(!ifm){
   ifm = FlexGlobals.topLevelApplication.focusManager;
  }
  return ifm;
  }
 }
}
于 2013-08-13T02:31:44.280 回答
1

这是完整的代码:

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
            xmlns:s="library://ns.adobe.com/flex/spark" 
            xmlns:mx="library://ns.adobe.com/flex/mx" 
            autoDrawBackground="true"
            width="100%"
            implements="mx.managers.IFocusManagerContainer">

    <fx:Script>
    <![CDATA[
        public function get defaultButton():IFlexDisplayObject {
            return null;
        }

        public function set defaultButton(value:IFlexDisplayObject):void {
            // do nothing
        }

        override public function get systemManager():ISystemManager {
            return null;
        }
    ]]>
    </fx:Script>

    <!-- other stuff -->

    <s:CheckBox id="enabledCheckbox" />

</s:ItemRenderer>

解决方案是实现 IFocusManagerContainer 或基本上它需要的功能。在我的情况下,我必须在 Scroller focusInHandler 处理程序中覆盖焦点事件的目标对象(组件)容器中的 systemManager getter。

我是这样想的。错误发生在 Scroller focusInHandler 中。焦点事件 (event.target) 的目标属性是 Checkbox(最后一个具有焦点的项)。Checkbox 的容器是我的 ItemRenderer。这是我实现 IFocusManagerContainer 接口的地方。我提到这一点是因为这条路径上有 5 个或更多父级别。

在 ItemRenderer 我添加了:

override public function get systemManager():ISystemManager {
    return null;
}

该方法是实现mx.managers.IFocusManagerContainer 接口时必须实现的方法。

该接口还要求我定义 defaultButton getter 和 setter,但没有必要解决此错误。在测试中,我删除了接口,删除了 defaultButton 成员并留下了 systemManager getter,只是它仍然解决了问题。

另外,感谢 noobsarepeople2 的帮助。

于 2012-08-05T02:16:28.340 回答
1

我在使用时遇到了这个问题PopUpManager

  1. 这是有关它的Adob​​e 错误报告
  2. 这是关于它的另一篇SO 帖子
  3. 这是另一篇可能相关也可能不相关的帖子(您没有提到导致此问题的原因)。

在我的情况下,我按照第一个和第二个链接的示例,Scroller并在适当的位置创建了一个子类进行空检查。这对于我的特殊情况来说很好,因此该应用程序没有遇到任何不良影响。也就是说,这个“修复”对我来说总是感觉有点老套。

于 2012-07-17T05:26:13.867 回答