如何在AS3中保留内容(图形,添加的显示对象等)的同时复制显示对象( Sprite ,影片剪辑等)?
Kirupa(http://www.kirupa.com/forum/showpost.php?p=1939827&postcount=172)最普遍建议的解决方案似乎没有复制任何图形或子显示对象:
// create a sprite
var s:Sprite = new Sprite();
// add a text field
var tf:TextField = new TextField();
tf.text = "nisse";
s.addChild(tf);
// draw something
s.graphics.lineStyle(1, 0x00FF00);
s.graphics.drawCircle(10, 10, 10);
s.x=100;
// add it to parent
this.addChild(s);
// create a copy using Kirupas duplicate display object solution
var sCopy:Sprite = duplicateDisplayObject(s, true) as Sprite;
sCopy.x = 200;
// confirem that the copy exists:
trace(sCopy);
// add to parent
this.addChild(sCopy); // <- works, but the original textfield and graphics are gone!
对此有什么建议吗? (如果不是,为什么?像其他任何对象一样,显示对象不是由应该可以复制的存储区域代表的吗?)
最佳答案
简短答案:
图形在运行时不是自省(introspection)的。无论Kirupa的代码在做什么,它都无法知道您绘制的形状,也无法复制或重新绘制它。 (被遗忘的文本字段可能是错误或设计使然,我不知道,但是形状没有变化。)
长答案:
DisplayObject不仅是一块内存,例如位图或字符串。它是一个对象,具有很多子属性,其中许多子属性也是对象,函数或类等。因此,当您说要复制一个子属性时,值得一问的确切含义是什么。子对象(例如数组)应该通过引用复制还是复制?如果有任何对象除了其子对象列表之外还包含对其他显示对象的引用,您如何知道要复制引用还是复制目标?如果某些原始对象正在监听键盘事件或运行计时器,那么重复项是否也可以在未注册的情况下工作?等等。
在OOP语言(如AS3)中,所有这些都是冗长的表达方式,没有通用的有意义的方式来复制对象。当然,您可以遍历MovieClips的树,制作新的树,然后尝试将属性从原始副本复制到副本-这就是Kirupa的代码可能正在做的事情。但是,除了琐碎的内容外,您发现的所有内容都无法满足您的需求。这就是为什么没有内置方法可以执行此操作的原因-因为在大多数情况下,它无法实现人们希望的操作。
最终,解决此类问题的真正方法是仔细研究需要完成的工作,并找到一种无需重复对象即可做到的方法。如果只需要原始图像的可视副本,则可以考虑每帧将原始图像绘制到位图中。也许最好的方法是构建一个包含与对象相关的所有信息的数据结构,以便您可以复制数据并基于该对象初始化对象。或者,也许您应该最初创建一个对象池,并维护每个对象,以便以后需要重复时可以拥有它们。
无论哪种方式,最终问题都是架构性的,因此解决方案也将必须如此。