I have added a chart in AnchorPane, and I want to get the bounds of its plot (chart-plot, I have marked it with cyan color), so that I could add some texts on top of it, but I should know its exact bounds according to its ancestor(s). If I do it manually, I may fail when the paddings' size of the nodes will be changed when resizing etc.
import javafx.application.Application;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
NumberAxis numberAxis = new NumberAxis();
LineChart chart = new LineChart(numberAxis, new NumberAxis());
chart.getYAxis().setSide(Side.RIGHT);
Node chartPlotArea = chart.lookup(".chart-plot-background");
chartPlotArea.setStyle("-fx-background-color: cyan");
AnchorPane anchorPane = new AnchorPane(chart);
AnchorPane.setTopAnchor(chart, 0.0);
AnchorPane.setRightAnchor(chart, 0.0);
AnchorPane.setBottomAnchor(chart, 0.0);
AnchorPane.setLeftAnchor(chart, 0.0);
Scene scene = new Scene(anchorPane);
primaryStage.setScene(scene);
primaryStage.setMaximized(true);
primaryStage.show();
}
}
So the question is how to get bounds of a node or chart-plot in my case according to its ancestor no matter how many are there?
Each JavaFX Node (subclass) instance can only be added to the JavaFX scene graph once. In other words, each Node instance can only appear in one place in the scene graph. If you try to add the same Node instance, or Node subclass instance, to the scene graph more than once, JavaFX will throw an exception!
getChildren. Gets the list of children of this Parent .
AnchorPane class is a part of JavaFX. AnchorPane allows the edges of child nodes to be anchored to an offset from the anchor pane's edges. If the anchor pane has a border and/or padding set, the offsets will be measured from the inside edge of those insets. AnchorPane inherits Pane class.
Leaf nodes are classes such as Rectangle , Text , ImageView , MediaView , or other such leaf classes which cannot have children. Only a single node within each scene graph tree will have no parent, which is referred to as the "root" node.
You already found Chart-Plot background node, and to get it coordinates according to its ancestor you need to simply call
chartPlotArea.getBoundsInParent();
and if there is more than one ancestor between them you can get char-plot bounds in AnchorPane coordinates system like this
Bounds bounds =
anchorPane.sceneToLocal(chartPlotArea.localToScene(chartPlotArea.getBoundsInLocal()));
A little trick here, is that they will be 0s until you show stage and let javaFX layout nodes, so you need to update it afte .show()
method, so result may look like this:
NumberAxis numberAxis = new NumberAxis();
LineChart chart = new LineChart(numberAxis, new NumberAxis());
chart.getYAxis().setSide(Side.RIGHT);
Node chartPlotArea = chart.lookup(".chart-plot-background");
chartPlotArea.setStyle("-fx-background-color: cyan");
Text text = new Text();
text.setText("Text");
AnchorPane anchorPane = new AnchorPane();
AnchorPane.setTopAnchor(chart, 0.0);
AnchorPane.setRightAnchor(chart, 0.0);
AnchorPane.setBottomAnchor(chart, 0.0);
AnchorPane.setLeftAnchor(chart, 0.0);
anchorPane.getChildren().addAll(chart, text);
Scene scene = new Scene(anchorPane);
primaryStage.setScene(scene);
primaryStage.setMaximized(true);
primaryStage.show();
Bounds bounds =
anchorPane.sceneToLocal(chartPlotArea.localToScene(chartPlotArea.getBoundsInLocal()));
double textRelativeX = (bounds.getMinX() + bounds.getMaxX()) / 2 - text.getLayoutBounds().getWidth() / 2;
double textRelativeY = bounds.getMinY() - text.getLayoutBounds().getHeight() / 2;
AnchorPane.setLeftAnchor(text, textRelativeX);
AnchorPane.setTopAnchor(text, textRelativeY);
And remember, that if you want coordinates change when resizing you can bind this to chart or chartPlotArea bound/width changes, something like this
chart.layoutBoundsProperty().addListener((observable, oldValue, newValue) -> {
double textRelativeXz = (newValue.getMinX() + newValue.getMaxX()) / 2 - text.getLayoutBounds().getWidth() / 2;
double textRelativeYz = newValue.getMinY() - text.getLayoutBounds().getHeight() / 3;
AnchorPane.setLeftAnchor(text, textRelativeXz);
AnchorPane.setTopAnchor(text, textRelativeYz);
});
EDIT: if you have more than one ancestor you can do like this to receive char-plot bounds in anchorPane coordinate system
Bounds bounds =
anchorPane.sceneToLocal(chartPlotArea.localToScene(chartPlotArea.getBoundsInLocal()));
this will work even if there more than one ancestor between them
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With