小能豆

Node Cloning in JavaFX

javascript

I have a JavaFX Node object, and I wish to clone it via code.

It’s my understanding that Java variables are reference-types, and simply doing something like clonedNode = oldNode would result in clonedNode pointing to oldNode.

It doesn’t appear that JavaFX has an in-built function for cloning Node objects. Hence, I attempted to write a cloning function myself as such (suppose I’m only working with Nodes of types Circle, Rectangle, Polygon, Line, Text and Group, and that I only care about the Fill, Stroke, Text and positional properties of the Node):

public static Node NodeClone(Node oldNode)
{
    Node clonedNode = null;

    if (oldNode.getClass() == Circle.class)
    {
        Circle oldCircle = (Circle)oldNode;

        Circle clonedCircle = new Circle();
        clonedCircle.setRadius(oldCircle.getRadius());
        clonedCircle.setFill(oldCircle.getFill());
        clonedCircle.setStroke(oldCircle.getStroke());
        clonedCircle.setStrokeWidth(oldCircle.getStrokeWidth());

        clonedNode = clonedCircle;
    }
    else if (oldNode.getClass() == Rectangle.class)
    {
        Rectangle oldRectangle = (Rectangle)oldNode;

        Rectangle clonedRectangle = new Rectangle();
        clonedRectangle.setWidth(oldRectangle.getWidth());
        clonedRectangle.setHeight(oldRectangle.getHeight());
        clonedRectangle.setFill(oldRectangle.getFill());
        clonedRectangle.setStroke(oldRectangle.getStroke());
        clonedRectangle.setStrokeWidth(oldRectangle.getStrokeWidth());

        clonedNode = clonedRectangle;
    }
    else if (oldNode.getClass() == Polygon.class)
    {
        Polygon oldTriangle = (Polygon)oldNode;

        Polygon clonedTriangle = new Polygon();
        LinkedList<Double> clonedPoints = new LinkedList<Double>(oldTriangle.getPoints());
        clonedTriangle.getPoints().setAll(clonedPoints);
        clonedTriangle.setFill(oldTriangle.getFill());
        clonedTriangle.setStroke(oldTriangle.getStroke());
        clonedTriangle.setStrokeWidth(oldTriangle.getStrokeWidth());

        clonedNode = clonedTriangle;
    }
    else if (oldNode.getClass() == Line.class)
    {
        Line oldLine = (Line)oldNode;

        Line clonedLine = new Line();
        clonedLine.setStartX(oldLine.getStartX());
        clonedLine.setStartY(oldLine.getStartY());
        clonedLine.setEndX(oldLine.getEndX());
        clonedLine.setEndY(oldLine.getEndY());
        clonedLine.setStroke(oldLine.getStroke());
        clonedLine.setStrokeWidth(oldLine.getStrokeWidth());

        clonedNode = clonedLine;
    }
    else if (oldNode.getClass() == Text.class)
    {
        Text oldText = (Text)oldNode;

        Text clonedText = new Text();
        clonedText.setFont(oldText.getFont());
        clonedText.setText(oldText.getText());
        clonedText.setFill(oldText.getFill());

        clonedNode = clonedText;
    }
    else if (oldNode.getClass() == Group.class)
    {
        Group oldGroup = (Group)oldNode;

        Group clonedGroup = new Group();

        for (int i = 0; i < oldGroup.getChildren().size(); i++)
            clonedGroup.getChildren().add(NodeClone(oldGroup.getChildren().get(i)));

        clonedNode = clonedGroup;
    }
    else
    {
        throw new java.lang.Error("ERROR: Attempting to clone an unrecognized JavaFX oldNode type!");
    }

    clonedNode.setTranslateX(oldNode.getTranslateX());
    clonedNode.setTranslateY(oldNode.getTranslateY());
    clonedNode.setLayoutX(oldNode.getLayoutX());
    clonedNode.setLayoutY(oldNode.getLayoutY());
    clonedNode.setRotate(oldNode.getRotate());

    return clonedNode;
}

With the function above returning a cloned instance of the provided Node object.

My question is, will calling the various Node‘s property setters directly on the results of the property getters result in the property values be passed by value or by reference?

In other words, will the properties of the cloned Node returned by the function above be truly unique or still point to the original Node‘s properties?

From my own testing, this function appears to indeed produce fully unique Nodes, but I wanted to verify before fully comitting to this Node cloning approach.

Thanks for reading my post, any guidance is appreciated.


阅读 72

收藏
2023-11-20

共1个答案

小能豆

I have a JavaFX Node object, and I wish to clone it via code.

It’s my understanding that Java variables are reference-types, and simply doing something like clonedNode = oldNode would result in clonedNode pointing to oldNode.

It doesn’t appear that JavaFX has an in-built function for cloning Node objects. Hence, I attempted to write a cloning function myself as such (suppose I’m only working with Nodes of types Circle, Rectangle, Polygon, Line, Text and Group, and that I only care about the Fill, Stroke, Text and positional properties of the Node):

public static Node NodeClone(Node oldNode)
{
    Node clonedNode = null;

    if (oldNode.getClass() == Circle.class)
    {
        Circle oldCircle = (Circle)oldNode;

        Circle clonedCircle = new Circle();
        clonedCircle.setRadius(oldCircle.getRadius());
        clonedCircle.setFill(oldCircle.getFill());
        clonedCircle.setStroke(oldCircle.getStroke());
        clonedCircle.setStrokeWidth(oldCircle.getStrokeWidth());

        clonedNode = clonedCircle;
    }
    else if (oldNode.getClass() == Rectangle.class)
    {
        Rectangle oldRectangle = (Rectangle)oldNode;

        Rectangle clonedRectangle = new Rectangle();
        clonedRectangle.setWidth(oldRectangle.getWidth());
        clonedRectangle.setHeight(oldRectangle.getHeight());
        clonedRectangle.setFill(oldRectangle.getFill());
        clonedRectangle.setStroke(oldRectangle.getStroke());
        clonedRectangle.setStrokeWidth(oldRectangle.getStrokeWidth());

        clonedNode = clonedRectangle;
    }
    else if (oldNode.getClass() == Polygon.class)
    {
        Polygon oldTriangle = (Polygon)oldNode;

        Polygon clonedTriangle = new Polygon();
        LinkedList<Double> clonedPoints = new LinkedList<Double>(oldTriangle.getPoints());
        clonedTriangle.getPoints().setAll(clonedPoints);
        clonedTriangle.setFill(oldTriangle.getFill());
        clonedTriangle.setStroke(oldTriangle.getStroke());
        clonedTriangle.setStrokeWidth(oldTriangle.getStrokeWidth());

        clonedNode = clonedTriangle;
    }
    else if (oldNode.getClass() == Line.class)
    {
        Line oldLine = (Line)oldNode;

        Line clonedLine = new Line();
        clonedLine.setStartX(oldLine.getStartX());
        clonedLine.setStartY(oldLine.getStartY());
        clonedLine.setEndX(oldLine.getEndX());
        clonedLine.setEndY(oldLine.getEndY());
        clonedLine.setStroke(oldLine.getStroke());
        clonedLine.setStrokeWidth(oldLine.getStrokeWidth());

        clonedNode = clonedLine;
    }
    else if (oldNode.getClass() == Text.class)
    {
        Text oldText = (Text)oldNode;

        Text clonedText = new Text();
        clonedText.setFont(oldText.getFont());
        clonedText.setText(oldText.getText());
        clonedText.setFill(oldText.getFill());

        clonedNode = clonedText;
    }
    else if (oldNode.getClass() == Group.class)
    {
        Group oldGroup = (Group)oldNode;

        Group clonedGroup = new Group();

        for (int i = 0; i < oldGroup.getChildren().size(); i++)
            clonedGroup.getChildren().add(NodeClone(oldGroup.getChildren().get(i)));

        clonedNode = clonedGroup;
    }
    else
    {
        throw new java.lang.Error("ERROR: Attempting to clone an unrecognized JavaFX oldNode type!");
    }

    clonedNode.setTranslateX(oldNode.getTranslateX());
    clonedNode.setTranslateY(oldNode.getTranslateY());
    clonedNode.setLayoutX(oldNode.getLayoutX());
    clonedNode.setLayoutY(oldNode.getLayoutY());
    clonedNode.setRotate(oldNode.getRotate());

    return clonedNode;
}

With the function above returning a cloned instance of the provided Node object.

My question is, will calling the various Node‘s property setters directly on the results of the property getters result in the property values be passed by value or by reference?

In other words, will the properties of the cloned Node returned by the function above be truly unique or still point to the original Node‘s properties?

From my own testing, this function appears to indeed produce fully unique Nodes, but I wanted to verify before fully comitting to this Node cloning approach.

Thanks for reading my post, any guidance is appreciated.

2023-11-20