您正在尝试将DisplayObject 直接写入文件,由于 Flash 处理任何对象的默认序列化的方式,Flash 引擎阻止了这种情况。为了将DisplayObject 保存到外部资源中,您需要在该对象的类以及您计划存储的任何对象类上使用IExternalizable。 writeExternal 的实现应该保存从头开始重建所述对象所需的所有数据,并且readExternal 还应该通过对嵌套显示对象执行addChild() 或将它们添加到对象可能包含的其他内部结构。
注意,其他答案包含使用 XML 或 JSON 进行自定义序列化的有效点,还包含需要导入的链接,特别是,flash.utils.registerClassAlias 和 flash.utils.getDefinitionByName 非常需要从序列化数据块重新创建结构.
举个例子:假设您有一个Board 类中的绘图板,以及一组可以使用鼠标拖动的矩形,它们的大小和颜色不同。矩形是定制的MovieClips 并且没有自己的类,但每个MovieClip 还分配了一个color 属性以简化它们的区别。这意味着您只需要在Board 类上实现IExternalizable。我们还假设Board 类有一个pieces 数组,其中包含指向嵌套矩形的所有链接,以及一个根据作为参数提供的宽度、高度和颜色创建一个新的适当大小的矩形的方法。 (您的情况可能对Board 的数据结构有更多要求,因此请密切关注)因此,序列化Board 的过程将收集嵌套MC 中的所有数据并将其按顺序填充到@提供了 987654341@,并且恢复 Board 实例的过程应该检索存储的数据,解析它以找到在哪里,创建嵌套的 MC,使其与存储的相同,正确定位它们,addChild() to self and rebuild the件`数组。
public class Board extends Sprite implements IExternalizable {
private var pieces:Array;
public function createRectangle(_width:Number,_height:Number,color:uint):MovieClip {
var mc:MovieClip=new MovieClip();
mc.graphics.beginFill(color);
mc.graphics.drawRect(0,0,_width,_height);
mc.graphics.endFill();
mc.color=color;
pieces.push(mc);
return mc;
}
对数据结构的改进已经可见 - 您需要将传递的 _width 和 _height 存储在 MC 中的某处,因为该 MC 的实际 width 将不同于默认线粗( 1,两边各 0.5)。不过,x 和 y 可以从 MC 的属性中正确检索。因此,将这两行都添加到createRectangle 中是必要的。
mc._width=_width;
mc._height=_height;
这样,序列化Board 变得更加容易。
public function writeExternal(output:IDataOutput):void {
var pl:int=pieces.length; // cache
output.writeInt(pl); // assuming we keep this array in integral state
for (var i:int=0;i<pl;i++) {
var _mc:MovieClip=pieces[i];
output.writeDouble(_mc.x); // this is usually not rounded when dragging, so saving as double
output.writeDouble(_mc.y);
output.writeDouble(_mc._width);
output.writeDouble(_mc._height);
output.writeInt(_mc._color);
}
// if anything is left about the "Board" itself, write it here
// I'm assuming nothing is required to save
}
要恢复,您需要从IDataInput 中读取数据按照与writeExternal 中写入的顺序完全相同,然后处理重建我们存储的显示列表。
public function readExternal(input:IDataInput):void {
// by the time this is called, the constructor has been processed
// so "pieces" should already be an instantiated variable (empty array)
var l:int;
var _x:Number;
var _y:Number;
var _width:Number;
var _height:Number;
var _color:uint;
// ^ these are buffers to read data to. We don't yet have objects to read these into
input.readInt(l); // get pieces length
for (var i:int=0;i<l;i++) {
input.readDouble(_x);
input.readDouble(_y);
input.readDouble(_width);
input.readDouble(_height);
input.readInt(_color);
// okay we got all the data representing the rectangle, now make one
var mc:MovieClip=createRectangle(_width,_height,_color);
mc.x=_x;
mc.y=_y;
addChild(mc); // createRectangle does NOT have addchild call
// probably because there are layers for the parts to be added to
// I'm assuming there are no layers here, but you might have some!
// pieces array is populated inside createRectangle, so we leave it alone
}
// read all the data you have stored after storing pieces
}
如果您的嵌套 MC 有一个也实现 IExternalizable 的类,您可以将整个数组保存在一条指令中,writeObject(pieces),这将使 Flash 遍历数组,找到它包含的所有数据并调用 @ 987654359@ 在任何嵌套对象上,本质上为数组中的每个实例调用该类的 writeExternal 函数。恢复这样的数组应该包括通过遍历数组并在每个恢复的实例上调用addChild() 来重建显示列表。
最后但并非最不重要的一点是,应在对自定义对象进行任何序列化或反序列化之前调用registerClassAlias()。调用它们的最佳位置可能是您的主对象的构造函数,因为它肯定会在您的应用程序包含的任何其他代码之前被调用。