Serialize a java.awt.geom.Area
I have the need to serialize an Are开发者_Go百科a object (java.awt.geom.Area) in a socket. However it doesn't seem to be serializable. Is there a way to do such thing? Maybe by converting it into a different object?
Thanks in advance
I found this workaround:
AffineTransform.getTranslateInstance(0,0).createTransformedShape(myArea)
This results in a shape that can be serialized.
Use XStream to trivially convert it to/from XML. You don't need your object to implement particular interfaces, and the serialisation is customisable.
From kieste's answer, this work-around can be derived.
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.io.IOException;
import java.io.Serializable;
public class SerialArea extends Area implements Serializable {
private static final long serialVersionUID = -3627137348463415558L;
/**
* New Area
*/
public SerialArea() {}
/**
* New Area From Shape
*/
public SerialArea(Shape s) {
super(s);
}
/**
* Writes object out to out.
* @param out Output
* @throws IOException if I/O errors occur while writing to the
* underlying OutputStream
*/
private void writeObject(java.io.ObjectOutputStream out)
throws IOException {
out.writeObject(AffineTransform.getTranslateInstance(0, 0).
createTransformedShape(this));
}
/**
* Reads object in from in.
* @param in Input
* @throws IOException if I/O errors occur while writing to the
* underlying OutputStream
* @throws ClassNotFoundException if the class of a serialized object
* could not be found.
*/
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException {
add(new Area((Shape) in.readObject()));
}
}
Since Java 1.6 seems like there is a more formal way of doing this.
All you have to do is convert the Area
object to a Path2D.Double
(or Path2D.Float
) object (which is Serializable
) with its corresponding append
method, taking also into account the winding rule at construction time (or even later, with a corresponding setter that exists).
To convert from Path2D.Double
to Area
, just use the Area
's constructor which accepts a Shape
.
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;
public class SerializeArea {
public static Path2D.Double toPath2D(final Area a) {
final PathIterator pi = a.getPathIterator(new AffineTransform());
final Path2D.Double path = new Path2D.Double();
switch (pi.getWindingRule()) {
case PathIterator.WIND_EVEN_ODD: path.setWindingRule(Path2D.WIND_EVEN_ODD); break;
case PathIterator.WIND_NON_ZERO: path.setWindingRule(Path2D.WIND_NON_ZERO); break;
default: throw new UnsupportedOperationException("Unimplemented winding rule.");
}
path.append(pi, false);
return path;
}
public static Area toArea(final Path2D path) {
return new Area(path);
}
public static void main(final String[] args) {
final Area area = new Area(new Ellipse2D.Double(0, 0, 100, 100));
area.intersect(new Area(new Rectangle2D.Double(0, 25, 100, 50))); //Creating something like a capsule.
System.out.println(toArea(toPath2D(area)).equals(area)); //Prints true.
}
}
精彩评论