在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并显示它。该模块有几个国家,每个州都有一个组,一个组有一个List,该List有一个ItemRenderer,该ItemRenderer有一个Checkbox。
该模块还有一个菜单。打开菜单时,弹出的菜单列出了Module可用的状态。当从弹出的菜单中选择一个项目时,我会切换到另一个状态。
当状态改变并且最后一项是复选框时,则生成错误。至少这就是我认为正在发生的事情。我推断出这是因为在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>
显示弹出窗口。弹出窗口是一个标题窗口,其中InspectorContainer(一个组)作为第一个元素。
弹出从主页状态(默认状态)更改为在线状态(当用户单击按钮时会发生这种情况)。在线状态有一个列表。 List有一个itemrenderer。 itemrenderer有一个复选框。选中该复选框。到目前为止一切顺利。
弹出窗口(InspectorContainer)有一个mx:MenuBar实例。当您单击菜单栏中的项目时,菜单栏会显示菜单项。
单击菜单列表中的项目。调用itemClick menuHandler。在此功能中,弹出窗口会更改状态。
这是发生错误的时间。
答案 0 :(得分: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第一次通过遍历来自其父,parent.parent和parent.parent.parent ...来获得它的focusmanager,但不幸的是,当PopUpManager.addPopUp(popUp)添加了uicomponent时这,FALSE);它的父级是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;
}
}
}
答案 1 :(得分:1)
使用PopUpManager
时遇到了这个问题。
在我的例子中,我在第一个和第二个链接上跟随了示例,并创建了一个Scroller
的子类,它在适当的位置进行了空检查。这对我的特殊情况很好,并且应用程序没有经历任何不良影响。这就是说这个“修复”对我来说总是让人觉得有点黑客。
答案 2 :(得分: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的容器是我的ItemRenderer。这是我实现IFocusManagerContainer接口的地方。我提到这个是因为沿着这条路径有5个或更多父级。
在ItemRenderer中我添加了:
override public function get systemManager():ISystemManager {
return null;
}
此方法是在实现mx.managers.IFocusManagerContainer接口时必须实现的方法。
该接口还要求我定义defaultButton getter和setter,但没有必要解决这个错误。在测试中,我删除了接口,删除了defaultButton成员并离开了systemManager getter,只是它仍然解决了问题。
另外,感谢noobsarepeople2的帮助。