AS3: невозможно скопировать объекты DisplayObject с содержимым? - PullRequest
5 голосов
/ 12 октября 2010

Как копировать экранные объекты (спрайты, видеоролики и т. Д.), Сохраняя их содержимое (графику, добавленные экранные объекты и т. Д.) В AS3?Наиболее часто предлагаемое решение от 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!

Есть ли какое-то сомнение в этом? (Если нет - почему?экранный объект, представленный областью памяти, которую можно копировать, как и любой другой объект?)

Ответы [ 5 ]

6 голосов
/ 12 октября 2010

Краткий ответ:

Графика не анализируется во время выполнения.Независимо от того, что делает код Кирупы, у него нет никакого способа узнать, какую форму вы нарисовали, и нет способа скопировать или перерисовать его.(Текстовое поле, которое можно пропустить, может быть ошибкой или по своему замыслу, я понятия не имею, но обойти форму невозможно).

Длинный ответ:

ADisplayObject - это не просто кусок памяти, как растровое изображение или строка.Это объект со множеством дочерних свойств, многие из которых также являются объектами, или функциями, или классами и т. Д. Поэтому, когда вы говорите, что хотите дублировать один, стоит спросить, что именно это означает.Должны ли дочерние объекты, например, массивы, копироваться по ссылке или дублироваться?Если какой-либо из объектов содержит ссылки на другие экранные объекты, помимо их списка дочерних элементов, как узнать, скопировать ли ссылку или дублировать цель?Если бы некоторые из исходных объектов прослушивали события клавиатуры или запускали таймеры, будут ли дубликаты работать без регистрации?И так далее, и так далее.

Все это является многословным способом сказать, что в языках ООП (таких как AS3) не существует универсально значимого способа дублирования объектов.Конечно, вы можете проходить через дерево MovieClips, создавать новые и пытаться копировать свойства из оригиналов в дубликаты - и это, по-видимому, и делает код Кирупы.Но для всего, кроме тривиального контента, как вы узнаете, это не даст вам того, что вы хотите.Вот почему нет встроенного способа сделать это - потому что большую часть времени он не будет делать то, на что надеялись люди.

В конечном счете, реальное решение проблемы такого рода - внимательно посмотреть на то, чтодолжно быть достигнуто, и найти способ сделать это без дублирования объектов.Если вам нужна только визуальная копия оригинала, вы можете рассмотреть возможность рисования оригинала в растровом изображении каждый кадр.Или, возможно, лучший подход - это создать структуру данных, содержащую всю информацию, относящуюся к вашему объекту, чтобы вы могли дублировать данные и инициализировать объект на их основе.Или, возможно, вам следует сначала создать пул объектов и поддерживать каждый из них, чтобы при необходимости дублировать их позже.

В любом случае, в конце концов, проблема архитектурная, поэтому решение также должно быть.

6 голосов
/ 12 октября 2010

Вы не можете изначально скопировать большинство внутренних классов, но вы можете захотеть заглянуть в IExternalizable (http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/utils/IExternalizable.html)

Это метод сериализации объектов, используемый внутри AMF. Он заставляет ваши объекты создаватьдва метода, readExternal и writeExternal. Идея состоит в том, что writeExternal позволяет упаковывать внутреннее состояние объектов в ByteArray, затем создается новый экземпляр вашего класса, и AMF передает этот ByteArray в метод readExternal, где вы можетевручную воссоздайте предыдущее внутреннее состояние объектов. Вызов методов и создание экземпляров выполняются с помощью метода ObjectUtil.copy () (http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/utils/ObjectUtil.html?filter_flex=4.1&filter_flashplayer=10.1&filter_air=2#copy()), если вы используете Flex SDK, в противном случае - реализацию копирования.выглядит следующим образом:

function copy(value:*):*{
  var buffer:ByteArray = new ByteArray();
  buffer.writeObject(value);
  buffer.position = 0;
  var result:Object = buffer.readObject();
  return result;
}

Как вы можете видеть здесь, только методы readObject и writeObject ByteArray фактически выполняют сериализацию, в действительности нет необходимости в классе ObjectUtil.

Вам также может понадобиться зарегистрировать псевдоним класса для классавы хотите скопировать, чтобы AMF знал, какой объект создать, иначе вы просто получите универсальные объекты на другом конце:

registerClassAlias("com.example.ExampleClass", com.example.ExampleClass);

Следует отметить, что вы не можете иметь требуемые параметры в конструкторе объектов, которые вы хотитекопировать этим методом, и что readObject ByteArray проверит объект, чтобы увидеть, реализует ли он IExternalizable, в противном случае он просто скопирует свои открытые свойства.Вот почему большинство встроенных классов не смогут скопировать.

В отношении копирования графики из экранных объектов можно использовать несколько методов:

Начиная с FP 10Графика имеет еще один полезный метод.

public function copyFrom(sourceGraphics:Graphics):void

(http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Graphics.html#copyFrom())

Так что, как только вы скопировали свой объект, вы можете затем вручную скопировать графику. Просто вставьте это вМетод copy (). Просто проверьте, расширяет ли он Sprite или MovieClip, а затем вызовите copyFrom (). Это было бы проще всего написать.

А вот еще один новый метод.

public function drawGraphicsData(graphicsData:Vector.<IGraphicsData>):void

(http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Graphics.html#drawGraphicsData())

Если вы должны были сохранить все команды в виде необработанных данных (даже в формате JSON или создать внутренние DTO), то напишите методы IExternalizable, чтобы скопировать команды в новый объект и заполнить заново.Графика с использованием этого метода. Это было бы проблематично писать, но это означало бы, что вы просто вызываете метод copy (), и у вас есть копия, Graphics и все, без какого-либо специального кода в методе copy (). Вы также можете вызватьГрафические методы динамически основаны на командах, так что вы можете заставить это работать в FP9 при необходимости.Это имеет дополнительный бонус, позволяющий вам изменять команды, поскольку в настоящее время это невозможно.Как только вы пишете в графику, вы застряли с ней.

2 голосов
/ 12 октября 2010

Это потому, что AS3 пытается быть объектно-ориентированным языком, и ООП способ сделать то, что вы пытаетесь сделать, это создать класс с помощью метода клонирования () :) Я думаю, что это будет наиболее гибким,безошибочный и легко читаемый способ копирования вашего объекта.

1 голос
/ 12 октября 2010

Вы не можете сделать точную копию, но вы можете легко создать суррогатное растровое изображение.Что работает для меня в большинстве случаев (заливки, эскизы и т. Д.)

См. Метод draw () BitmapData.

0 голосов
/ 24 мая 2011
var newObject:DisplayObject;
newObject = originalObject;

addChild(newObject);

Вот как я это сделаю.Он работал со всеми типами экранных объектов (mc's, sprites, textField и т. Д.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...