在滚轮类焦点管理错误(Focus Manager bug in Scroller class)

2019-10-17 01:15发布

在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中,它增加了一个模块并显示它。 该模块有几个国家,每个国家是一个集团,一个集团有一个列表,则该列表具有的ItemRenderer,这ItemRenderer的都有一个复选框。

该模块还具有一个菜单。 当菜单打开菜单弹出列表模块的可用状态。 当从菜单中选择一个项目弹出我改变到另一种状态。

当状态发生变化,最后一个项目是复选框,然后生成错误。 至少这是我认为正在发生的事情。 我推断这是因为在滚轮类的操作是处理的事件。 该事件是当前的目标。 也就是说目前的目标是复选框。

更新 -重现步骤

// 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. 在离家状态(默认状态),以联机状态弹出的变化(当用户点击一个按钮,出现这种情况)。 在线状态有一个列表。 名单已经确定itemRenderer的。 的itemRenderer都有一个复选框。 选中该复选框。 到现在为止还挺好。

  3. 弹出(InspectorContainer)具有MX:MenuBar实例。 当您在菜单栏单击一个项目的菜单栏将显示一个菜单项。

  4. 在菜单中单击列表中的项目。 该itemClick在menuHandler被调用。 在此功能的弹出状态变化。

这是发生错误时。

Answer 1:

错误的主要振振有辞是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遍历通过从其父,parent.parent和parent.parent.parent ......,但不幸的是,当被PopUpManager.addPopUp加入uicomponent得到它的FocusManager第一次(弹出,这一点,假); 它的母公司是的SystemManager,它的parent.parent是舞台,他们要么没有了IFocusManagerContainer,所以他们要么没有的FocusManager属性,因此结果是空。

最后,我的解决办法是重写直接使用组件,如果你需要修复一个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;
  }
 }
}


Answer 2:

我用的时候就遇到了这个问题PopUpManager

  1. 这里是的Adobe错误报告就可以了。
  2. 这里还有一个SO张贴关于它 。
  3. 这是另一篇文章 ,可能会或可能不相关(你没有提到什么导致了这个问题)。

在我来说,我也跟着在第一和第二链路的例子,由一个子类Scroller ,做在适当的地方空校验。 这是罚款,我的具体情况和应用程序没有经历过任何不良影响的结果。 认为这“修复”一直感到一点点哈克给我。



Answer 3:

下面是完整的代码:

<?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中或基本功能。 在我而言,我不得不重写systemManager的吸气剂,在滚轮focusInHandler处理焦点事件的目标对象(组件)的容器。

我想通了这种方式。 在滚轮focusInHandler出现的错误。 焦点事件(event.target)的目标属性是复选框(最后一个项目有焦点)。 复选框的容器是我的ItemRenderer的。 这是我实现了IFocusManagerContainer接口。 我提到这一点,因为有沿着这条道路5级或更多父水平。

在我的ItemRenderer补充:

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

这种方法是你,当你实现mx.managers.IFocusManagerContainer接口来实现的方法。

该接口还需要我来定义defaultButton getter和setter,但没有必要解决这个错误。 在测试中,我删除的接口,去掉了defaultButton成员离开了systemManager的getter和只用它仍然解决了这个问题。

此外,由于noobsarepeople2寻求帮助。



文章来源: Focus Manager bug in Scroller class