I want to clone a Canvas object, which contains a Degrafa Surface with several Geometry shapes.
I tried the naive approach:
return ObjectUtil.copy(graph_area) as Canvas;
which resulted in errors:
TypeError: Error #1034: Type Coercion failed: cannot convert Object#63b1b51 to com.degrafa.geometry.Geometry.
TypeError: Error #1034: Type Coercion failed: cannot convert Object#63b1039 to com.degrafa.geometry.Geometry.
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at mx.core::Container/addChildAt()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:2196]
at mx.core::Container/addChild()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:2140] ...
What you want is called a deep copy, generate a new instance with the same information of the original.
The only way I know how to do it is using ByteArray as follows:
private function clone(source:Object):*
{
var buffer:ByteArray = new ByteArray();
buffer.writeObject(source);
buffer.position = 0;
return buffer.readObject();
}
AS3 is really lacking Object.clone()...
ObjectUtil
The static method ObjectUtil.copy() is AS3's "Object.clone()":
public static function copy(value:Object):Object
Copies the specified Object and
returns a reference to the copy. The
copy is made using a native
serialization technique. This means
that custom serialization will be
respected during the copy.
This method is designed for copying
data objects, such as elements of a
collection. It is not intended for
copying a UIComponent object, such as
a TextInput control. If you want to
create copies of specific UIComponent
objects, you can create a subclass of
the component and implement a clone()
method, or other method to perform the
copy.
I found myself trying something more like this alas it still doesn't seem to copy a TextArea (aka UI Object)...
public function duplicateObject(sourceObject:*, targetObject:*):void {
var buffer:ByteArray = new ByteArray();
buffer.writeObject(sourceObject);
buffer.position = 0;
targetObject = buffer.readObject();
}
i got the same problem (for a NamedEntity interface i created), looked for the answer here, but only got it working making a call to the registerClassAlias method (which i took from http://richapps.de/?p=34). Just like that:
public static function clone(namedEntity:NamedEntity):NamedEntity {
registerClassAlias('test',ReflectionUtil.classByObject(namedEntity));
var returnObject:NamedEntity = ObjectUtil.copy(namedEntity) as NamedEntity;
}
I don't think ObjectUtil.copy will work for cloning a canvas.
According to the flex doc :
Copy
This method is designed for copying data objects, such as elements of a collection. It is not intended for copying a UIComponent object, such as a TextInput control. If you want to create copies of specific UIComponent objects, you can create a subclass of the component and implement a clone() method, or other method to perform the copy.
Related
When using ObjectUtil.copy() on my object, I get the following error
Argument count mismatch on foo.bar::MyObject(). Expected 1, got 0.
MyObject's constructor takes in one parameter. Is there a way for me to clone, or copy it?
Use the ObjectUtil.clone method. That should do deep copies.
However, I'm not sure if that will solve the issue.
In Flex 4.5 Neither copy, nor clone, create a new version of the object using the new keyword; therefore the constructor is never called. Both do byte array copies. I'd be interested to see your code.
I use:
public static function clone(source:Object):* {
var myBA:ByteArray = new ByteArray();
myBA.writeObject(source);
myBA.position = 0;
return(myBA.readObject());
}
Never let me down.
In the code below, a reference type is being added. How can i do this value type?
imgList.Items.Add(imgList.Items[0]);
imgList.Items[imgIndex].Data = input; <== **This updates the 0th and the newly added element which is the issues**
Please advise
In order to avoid this issue, you need to clone imgList.Items[0] before adding it to imgList.Items. This basically involves creating a new object of the same type and populating it with data from the original.
The complexity of doing so depends on what the object is, but look at the answers to this question for some tips on cloning objects.
Edit: I forgot that .MemberwiseClone was protected.
You don't say in your code what the type of object is that you're adding to the list. If it's a class of yours, you can add a method to return a copy:
public MyType ShallowCopy()
{
return (MyType)this.MemberwiseClone();
}
and use
imgList.Items.Add(imgList.Items[0].ShallowCopy());
Or you can add a copy constructor:
public MyType(MyType original)
{
// Copy each of the properties from original
this.Data = original.Data;
}
and use
imgList.Items.Add(new MyType(imgList.Items[0]));
Im trying to connect a Flash client to BlazeDS. There has been some success with this from others using the vanilla BlazeDS setup. However I'm using the new Spring BlazeDS Integration from springsource and running aground.
The flash client actually seems to be working in that I can see the correct data in the body of the returned object, but for some reason unknown it fails casting as an IMessage. It fails in PollingChannel.as on this line with the subject line error
var messageList:Array = msg.body as Array;
for each (var message:IMessage in messageList) <--
On application load I register a whole bunch of classes like so
registerClassAlias( "flex.messaging.messages.RemotingMessage", RemotingMessage );
registerClassAlias("mx.messaging.messages.IMessage", IMessage);
etc..
my code is basically
var channelSet:mx.messaging.ChannelSet = new mx.messaging.ChannelSet();
var channel:mx.messaging.channels.AMFChannel = new AMFChannel("my-amf", "http://localhost:8400/SpringA/messagebroker/amf");
channelSet.addChannel(channel);
var consumer:mx.messaging.Consumer = new Consumer();
consumer.channelSet = channelSet;
consumer.destination = "simple-feed";
consumer.subscribe();
consumer.addEventListener(MessageEvent.MESSAGE, test);
private function test(event:IMessage)
{
trace("msg..");
// breakpoint never makes it here
}
I have a flex client which works 100% with same destination/channel.
The error in the title means that you, for some reason, got an object that is not implementing or extending the IMessage interface, therefore the loop can not cast it in this part:
for each (var message:IMessage in messageList){
Either you should somehow make sure that you don't add anything that is not extending or implementing IMessage, or check if the variable IS actually ext./imp. it. Also - if you want to do that, you will have to change the for each like this:
for each (var obj in messageList){
if (obj is IMessage){
var message:IMessage = obj as IMessage;
// DO STUFF HERE
}
}
Add this Object mapping:
registerClassAlias("flex.messaging.io.ObjectProxy", ObjectProxy);
If on your Java VO objects you have overridden the hashcode() method, this situation could happen.
Remove the hashcode() override (if you are able to).
See my blog for the backstory on how I discovered this. http://squaredi.blogspot.com/2013/12/remoting-landmine-without-stack-trace.html
I had the same error when trying to send an actionscript object to the backend. My problem was that my c# equivalent object was missing an public parameterless constructor.
I'm trying to convert an image in my assets folder
"./assets/image1.png"
to type Object. It needs to be Object because that's what the function I'm using it in is expecting.
Any ideas what would be the simplest way to do this?
Do you mean something like :
[Embed(source="assets/logo.jpg")]
private var logo:Class;
private function init(e:Event):void
{
this.displayImage(logo as Object);
}
private function displayImage(img:Object):void
{
//Assuming you have an image control on stage with an instance
//name of "myImage"
myImage.source = img;
}
If the function you are passing the image to is expecting an Object object, you can in pass anything, it won't reject it. That doesn't mean the function will work correctly, though. Any value will be an Object (except for undefined, which will be accepted but coerced to null and maybe some other strange cases).
So, assuming you didn't write the function yourself, do you have any doc that describes what it expects? Or maybe you have the source code for it?. Otherwise, if the only thing you know about what this function expects is that the parameter must be of type Object... you're in trouble, I think.
Why don't you create a new Object containing the information about the image... including the path.
var obj:Object = new Object();
obj.path = "/assets/image.jpg";
obj.height = 32;
obj.width = 32;
trace(obj.path);
// or, if Flex
Alert.show(obj.path);
And then just pass the new Object into the function and access it like I have above.
I've just found a strange error when deserializing from a ByteArray, where Vectors cannot contain types that extend Array: there is a TypeError when they are deserialized.
TypeError: Error #1034: Type Coercion failed: cannot convert []#4b8c42e1 to com.myapp.ArraySubclass.
at flash.utils::ByteArray/readObject()
at com.myapp::MyApplication()[/Users/aaaidan/MyApp/com/myapp/MyApplication.as:99]
Here's how:
public class Application extends Sprite {
public function Application() {
// register the custom class
registerClassAlias("MyArraySubclass", MyArraySubclass);
// write a vector containing an array subclass to a byte array
var vec:Vector.<MyArraySubclass> = new Vector.<MyArraySubclass>();
var arraySubclass:MyArraySubclass = new MyArraySubclass();
arraySubclass.customProperty = "foo";
vec.push(arraySubclass);
var ba:ByteArray = new ByteArray();
ba.writeObject(arraySubclass);
ba.position = 0;
// read it back
var arraySubclass2:MyArraySubclass = ba.readObject() as MyArraySubclass; // throws TypeError
}
}
public class MyArraySubclass extends Array {
public var customProperty:String = "default";
}
It's a pretty specific case, but it seems very odd to me. Anyone have any ideas what's causing it, or how it could be fixed?
well, it seems array serialization is hardcoded. you should definitely post a bug report.
actually the code you posted doesn't throw an error since ba.readObject() as MyArraySubclass is simply null. MyArraySubclass(ba.readObject()) however would.
what you could try to fix it, would be to implement IExternalizable, altough I'm not sure it'll work any better.
I guess the problem is that Array is a very very special class in ActionScript (in the sense that in some way it is nothing more than any other dynamic class, but in other ways it's not at all) which leads to a lot of Array-specific code in the VM. Also, a question is, why do you need to subclass Array?