Reputation: 192
I'm new to JavaFX and I have troubles with bindings.
I'm coding a game in which I draw lines between panes contains in the cells of a GridPane
. I can draw lines with the code below, but I'd like to have the line coordinates to scale as the pane gets bigger when I resize the window.
The Pane
s and the GridPane
already resize as wanted, and I've managed to bind the line's width to the size of the scene (cellSize is a binding on the scene width/height).
Pane lastPane = panes[lastC][lastR];
Pane curPane = panes[c][r];
Bounds boundsInSceneLast = lastPane.localToScene(lastPane.getBoundsInLocal());
Bounds boundsInSceneCur = curPane.localToScene(curPane.getBoundsInLocal());
double lastX = (boundsInSceneLast.getMinX() + boundsInSceneLast.getMaxX())/2;
double lastY = (boundsInSceneLast.getMinY() + boundsInSceneLast.getMaxY())/2;
double x = (boundsInSceneCur.getMinX() + boundsInSceneCur.getMaxX())/2;
double y= (boundsInSceneCur.getMinY() + boundsInSceneCur.getMaxY())/2;
Line line = new Line(lastX, lastY, x, y);
line.setStroke(Color.web(couleurs.get(symbole)));
line.strokeWidthProperty().bind(cellSize.divide(10));
line.setStrokeLineCap(StrokeLineCap.BUTT);
anchor.getChildren().add(line);
lines.get(symbole).add(line);
anchor
is an AnchorPane
which is the root of my Scene
and lines
is a HashMap
which keeps track of the lines, but those shouldn't be relevant to my problem.
I'm sure it can be done pretty simply but I've searched the web pretty deeply and all I could understand and try wasn't getting the job done so I'm asking for your help.
Thanks in advance !! :)
Upvotes: 0
Views: 418
Reputation: 82461
It's problematic to listen to the bounds of a Node
in the scene since there is no property for the scene bounds and every Parent
on the path to the root node of the scene could apply a transform that require you to adjust the position of the line ends. This would require you to add a listener to descendant of the Pane
s.
It would be simpler to make the lines a part of the GridPane
itself as unmanaged nodes. This allows you to work with the bounds of the nodes in the GridPane
:
final Pane lastPane = panes[lastC][lastR];
final Pane curPane = panes[c][r];
final Line line = new Line();
line.setStroke(Color.web(couleurs.get(symbole)));
line.strokeWidthProperty().bind(cellSize.divide(10));
line.setStrokeLineCap(StrokeLineCap.BUTT);
InvalidationListener listener = o -> {
Bounds boundsInSceneLast = lastPane.getBoundsInParent();
Bounds boundsInSceneCur = curPane.getBoundsInParent();
double lastX = (boundsInSceneLast.getMinX() + boundsInSceneLast.getMaxX())/2;
double lastY = (boundsInSceneLast.getMinY() + boundsInSceneLast.getMaxY())/2;
double x = (boundsInSceneCur.getMinX() + boundsInSceneCur.getMaxX())/2;
double y = (boundsInSceneCur.getMinY() + boundsInSceneCur.getMaxY())/2;
line.setStartX(lastX);
line.setStartY(lastY);
line.setEndX(x);
line.setEndY(y);
};
// listen to location & size changes of panes in the GridPane
lastPane.boundsInParentProperty().addListener(listener);
curPane.boundsInParentProperty().addListener(listener);
// initial refresh
listener.invalidated(null);
// add line to GridPane without considering it for layout
line.setManaged(false);
gridPane.getChildren().add(line);
lines.get(symbole).add(line);
Upvotes: 1