碰到这样一个奇怪的问题:

一个Flex 2项目,其中算上Base state一共有三个state(以下简称baseState、state1、state2),从baseState到state2的互相切换都很正常,切换的state1也很正常。但是一旦切换到state1后,就不能再切换回state2或者baseState了,报错如下:

1
2
3
4
5
6
7
8
9
10
ArgumentError: Error #2025: 提供的 DisplayObject 必须是调用者的子级。
at flash.display::DisplayObjectContainer/removeChild()
at mx.core::Container/removeChild()
at mx.states::AddChild/remove()
at mx.core::UIComponent/::removeState()
at mx.core::UIComponent/::commitCurrentState()
at mx.core::UIComponent/setCurrentState()
at mx.core::UIComponent/set currentState()
at stateTest2/::baseHandler()
at stateTest2/___Button1_click()

百思不得其解,进行了无数次测试后发现问出出在ApplicationControlBar组件上。

原来,在项目设计中,baseState是一个loading效果,state1则是主要界面内容。在state1中,有一个ApplicationControlBar组件,这个组件有一个dock属性。当dock属性值为true的时候,ApplicationControlBar会自动贴紧在界面上边缘,为了实现这个功能,或许Flex自动将ApplicationControlBar组件的层级提升至最高层。这样,当切换到其他state需要自动删除此组件的时候,由于组件处于最高层而不能被删除,就出现了上面的错误。

知道错误的原因,解决方法也就非常简单了:将dock属性设置为false或者直接删除dock属性即可。

也可以把ApplicationControlBar组件作为其他组件(例如VBox)的子级添加,然后通过操作其父组件来显示它。

如果是Debug版本的Flash Player,测试下面的Demo就可以看到出错信息:

ApplicationControlBar组件对State的影响 未修改前效果

您的浏览器不支持JavaScript,或者您禁用了JavaScript。

请启用浏览器的JavaScript支持。

如果您确认启用了JavaScript,请使用下面的链接升级Flash Player到最新版本:

安装最新的Flash Player插件

ApplicationControlBar组件对State的影响 修改后效果

您的浏览器不支持JavaScript,或者您禁用了JavaScript。

请启用浏览器的JavaScript支持。

如果您确认启用了JavaScript,请使用下面的链接升级Flash Player到最新版本:

安装最新的Flash Player插件

源码(未修改前):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:Script>
<![CDATA[
private function baseHandler():void
{
currentState = "";
}
private function state1Handler():void
{
currentState = "state1";
}
private function state2Handler():void
{
currentState = "state2";
}
]]>
</mx:Script>
<mx:Style>
Application
{
font-size:12;
}
</mx:Style>
<mx:states>
<mx:State name="state1">
<mx:AddChild position="lastChild">
<mx:ApplicationControlBar id="appBar" dock="true" width="100%">
<mx:Label text="state1 in ApplicationControlBar"/>
</mx:ApplicationControlBar>
</mx:AddChild>
<mx:RemoveChild target="{label1}"/>
</mx:State>
<mx:State name="state2">
<mx:AddChild position="lastChild">
<mx:Label text="state2"/>
</mx:AddChild>
<mx:RemoveChild target="{label1}"/>
</mx:State>
</mx:states>
<mx:HBox>
<mx:Button label="切换到baseState" click="baseHandler()"/>
<mx:Button label="切换到state1" click="state1Handler()"/>
<mx:Button label="切换到state2" click="state2Handler()"/>
</mx:HBox>
<mx:Label text="base state" id="label1"/>
</mx:Application>

留言

2007-06-13
次访问