跟踪在 javafx 中绑定的节点的变化
track change of nodes bound in javafx
我想要在这个 post 中提出的相同问题
track changes of nodes bound in JavaFX
我有这样的东西:
(编辑)
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);
}
}
但问题是更改后的方法没有正确调用...它只调用了一次....如果我在更改后的方法而不是旧方法中添加此代码它被正确调用...但是非常非常慢
FloatCircle fc = new FloatCircle(node);
fc.rectangle = rectangle ;
fc.setLocation(newValue, directionID, alignment);
谁能帮帮我?
谢谢...
由于本例中的 Button
和 Circle
位于同一父窗格中,您显然可以通过将圆圈的位置绑定到按钮的位置来更简单(更有效)地完成此操作boundsInParentProperty()
。我假设您这样做是因为您有一个真实的应用程序,其中两个节点位于不同的父节点中。
看起来 localToSceneTransformProperty()
正在过早地收集垃圾(另请参阅 this)。您可以使用侦听器而不是绑定来解决此问题:
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);
}
}
我想要在这个 post 中提出的相同问题 track changes of nodes bound in JavaFX
我有这样的东西: (编辑) 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);
}
}
但问题是更改后的方法没有正确调用...它只调用了一次....如果我在更改后的方法而不是旧方法中添加此代码它被正确调用...但是非常非常慢
FloatCircle fc = new FloatCircle(node);
fc.rectangle = rectangle ;
fc.setLocation(newValue, directionID, alignment);
谁能帮帮我? 谢谢...
由于本例中的 Button
和 Circle
位于同一父窗格中,您显然可以通过将圆圈的位置绑定到按钮的位置来更简单(更有效)地完成此操作boundsInParentProperty()
。我假设您这样做是因为您有一个真实的应用程序,其中两个节点位于不同的父节点中。
看起来 localToSceneTransformProperty()
正在过早地收集垃圾(另请参阅 this)。您可以使用侦听器而不是绑定来解决此问题:
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);
}
}