Reputation: 164
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?
Upvotes: 7
Views: 649
Reputation: 456
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
Upvotes: 3