Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

track change of nodes bound in javafx

I want same thing that asked in this post track changes of nodes bound in JavaFX

I have something like this : (Edited) SSCCE:

public class FloatCircle {

Node node;


Circle rectangle;
Bounds localToScreen;
static ArrayList<ObjectBinding> list = new ArrayList<>();
private ObjectBinding<Bounds> boundsInScene ;
Pane root ;

public FloatCircle(Node node,Pane root) {
    this.node = node;
   this.root =root;
    this.rectangle = new Circle();
    this.rectangle.setManaged(false);

    initSetting();

}



public Circle getFloatCircle() {
    return rectangle;
}

public void initSetting() {

   boundsInScene = Bindings.createObjectBinding(
            () -> node.localToScene(node.getBoundsInLocal()),
            node.localToSceneTransformProperty(),
            node.boundsInLocalProperty());
    boundsInScene.addListener(new ChangeListener<Bounds>() {

        @Override
        public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) {
             setLocation(newValue);
            System.err.println("CHANGED!!!!!!");
        }

    });
    localToScreen = node.localToScene(node.getBoundsInLocal());
    setLocation(localToScreen);
    addCircle();
}

public void setLocation(Bounds localToScreen) {
    int r = 10;
            rectangle.setCenterX(localToScreen.getMinX() - r);
            rectangle.setCenterY(localToScreen.getMinY() - 5);
            rectangle.setRadius(r);

    //    return rect;

}

public void addCircle(){
            root.getChildren().add(rectangle);

}

}




public class SelfContained extends Application {

ArrayList<Node> nodes = new ArrayList<>();

@Override
public void start(Stage primaryStage) {
    Button btn = new Button();

    StackPane root = new StackPane();
    root.getChildren().add(btn);
    nodes.add(btn);

    Scene scene = new Scene(root, 300, 250);

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();

    for (int i = 0; i < nodes.size(); i++) {
        Node n = nodes.get(i);
        FloatCircle floatCircle = new FloatCircle(n, root);

    }
}

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

}

but the problem is changed method doesn't called correctly...It is called just one time....if I add this code in changed method instead of the old one It is called correctly...But it is very very slow

           FloatCircle fc = new FloatCircle(node);
           fc.rectangle = rectangle ;
           fc.setLocation(newValue, directionID, alignment);

Can anyone help me? Thank's...

like image 603
faraa Avatar asked Jul 22 '15 13:07

faraa


People also ask

Can a node be placed in a scene JavaFX?

Node objects may be constructed and modified on any thread as long they are not yet attached to a Scene in a Window that is showing. An application must attach nodes to such a Scene or modify them on the JavaFX Application Thread.

What does getChildren return in JavaFX?

The getChildren() method of the Pane parent class returns the ObservableList<Node> that contains all the elements in the Pane .

What is JavaFX scene node?

The JavaFX Node class, javafx. scene. Node , is the base class (superclass) for all components added to the JavaFX Scene Graph. The JavaFX Node class is abstract, so you will only add subclasses of the Node class to the scene graph.


1 Answers

Since the Button and the Circle in this example are in the same parent pane, you could obviously do this much more simply (and efficiently) just by binding the circle's location to the button's boundsInParentProperty(). I assume that you are doing it this way because you have a real application in which the two nodes are in different parents.

It looks like the localToSceneTransformProperty() is getting garbage collected prematurely (see also this). You can fix this using a listener instead of a binding:

public static class FloatCircle {

    Node node;

    Circle rectangle;
    Pane root;

    public FloatCircle(Node node, Pane root) {
        this.node = node;
        this.root = root;
        this.rectangle = new Circle();
        this.rectangle.setManaged(false);

        initSetting();

    }

    public Circle getFloatCircle() {
        return rectangle;
    }

    public void initSetting() {

        ChangeListener<Object> updater = (obs, oldValue, newValue) -> 
            setLocation(node.localToScene(node.getBoundsInLocal()));
        node.boundsInLocalProperty().addListener(updater);
        node.localToSceneTransformProperty().addListener(updater);

        setLocation(node.localToScene(node.getBoundsInLocal()));
        addCircle();
    }

    public void setLocation(Bounds localToScreen) {
        int r = 10;
        rectangle.setCenterX(localToScreen.getMinX() - r);
        rectangle.setCenterY(localToScreen.getMinY() - 5);
        rectangle.setRadius(r);
    }

    public void addCircle() {
        root.getChildren().add(rectangle);

    }

}
like image 70
James_D Avatar answered Sep 22 '22 13:09

James_D