1

I am creating an animation, where I have two circles joined by a line. When the nodes(circles) move, I want the line to bind their centres. What I have tried?

import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
import javafx.util.Duration;

public class BindIt extends Application {

    @Override
    public void start(Stage primaryStage) {
        DoubleProperty startX = new SimpleDoubleProperty(100);
        DoubleProperty startY = new SimpleDoubleProperty(100);
        DoubleProperty endX = new SimpleDoubleProperty(300);
        DoubleProperty endY = new SimpleDoubleProperty(300);
        Line line = new Line(100, 100, 300, 300);
        line.startXProperty().bind(startX);
        line.startYProperty().bind(startY);
        line.endXProperty().bind(endX);
        line.endYProperty().bind(endY);
        Circle c1 = new Circle(25);
        c1.setCenterX(100);
        c1.setCenterY(100);
        c1.centerXProperty().bind(startX);
        c1.centerYProperty().bind(startY);

        Circle c2 = new Circle(25);
        c2.setCenterX(300);
        c2.setCenterY(300);
        c2.centerXProperty().bind(endX);
        c2.centerYProperty().bind(endY);


        Group root = new Group();
        root.getChildren().add(line);
        root.getChildren().add(c1);
        root.getChildren().add(c2);

        Scene scene = new Scene(root, 500, 500);

        primaryStage.setTitle("Bind the line!");
        primaryStage.setScene(scene);
        final Timeline timeline = new Timeline();
        timeline.getKeyFrames().addAll(new KeyFrame(Duration.millis(0)), new KeyFrame(Duration.millis(2000), new KeyValue(c1.centerXProperty(), 200)));
        timeline.play();

        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

if I remove all the lines with "bind" I get the circle moving. But with bind I get error saying "cannot bind etc" I mean these lines

line.startXProperty().bind(startX);
line.startYProperty().bind(startY);
line.endXProperty().bind(endX);
line.endYProperty().bind(endY);

c1.centerXProperty().bind(startX);
c1.centerYProperty().bind(startY);

c2.centerXProperty().bind(endX);
c2.centerYProperty().bind(endY);

Without these lines the code is working. But the binding doesn't happen.

Can someone tell me where am I doing wrong?

Anil
  • 53
  • 1
  • 6
  • what result do you get? Does anything move and how? – Andrei Nikolaenko Mar 16 '15 at 07:29
  • @AndreiNikolaenko Without the lines having "bind" the node moves correctly. but line binding is not working. – Anil Mar 16 '15 at 07:32
  • Why to bind `endX` and `endY`? You don't seem to change their values at all. – ItachiUchiha Mar 16 '15 at 09:12
  • `new KeyValue(c1.centerXProperty(), 200)` -- change to `new KeyValue(startX, 200)` – Andrei Nikolaenko Mar 16 '15 at 09:24
  • @ItachiUchiha in this example I am not moving c2, but I may move two nodes. – Anil Mar 16 '15 at 10:31
  • @AndreiNikolaenko this works, any idea what is wrong with the original method? – Anil Mar 16 '15 at 10:36
  • @AndreiNikolaenko I changed this to `c1.centerXProperty().bind(startX)` to `startX.bind(c1.centerXProperty())`, that worked too. It seems the value binding something else can't be changed. Only independent things can change, that seems to be the reason, Thanks anyway. – Anil Mar 16 '15 at 11:01
  • Might be a duplicate of: [JavaFX: How to connect two Nodes by a Line?](http://stackoverflow.com/questions/19748744/javafx-how-to-connect-two-nodes-by-a-line), the solution of which contains logic for binding the center of an arbitrarily shaped node (based on the nodes boundsInParent). – jewelsea Mar 16 '15 at 17:37

2 Answers2

1

I found the answer, if you bind a property it is dependent variable, so it can't be changed, only independent variables can be changed. So I changed

c1.centerXProperty().bind(startX) 

to

startX.bind(c1.centerXProperty())

It worked. Thanks everyone for the comments.

Anil
  • 53
  • 1
  • 6
0

You get the error

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: Circle.centerX : A bound value cannot be set.

That says it all. You can't set the circle's center X and Y in the Timeline. Instead of center(X/Y)Property you should use the double properties.

Roland
  • 18,114
  • 12
  • 62
  • 93