I am writing a vector canvas in JavaFX (vector graphics, just shapes are displayed on the canvas): well, so that you can move around and zoom in on it.
Since the position of the upper-left corner of the node changes when translating, and it no longer responds to clicks, I decided to make a panel inside the canvas itself, on which everything will be displayed.
Inside the VectorCanvas
there is a VectorCanvasContent
.
Lines are added to VectorCanvasContent
, but for some reason they are not visible (although they are there, I added a listener that outputs "!!!" when you click on them, and checked).
If I draw lines on the canvas itself, then they are visible.
What is the problem?
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import java.util.function.Consumer;
public class VectorCanvas extends Pane {
public class VectorCanvasContent extends Pane {
public static final Consumer<VectorCanvas> DEFAULT_DRAWER = canvas -> {
Line[] lines = {
new Line(0, 0, canvas.getWidth(), 0),
new Line(canvas.getWidth(), 0, canvas.getWidth(), canvas.getHeight()),
new Line(canvas.getWidth(), canvas.getHeight(), 0, canvas.getHeight()),
new Line(0, canvas.getHeight(), 0, 0),
new Line(0, 0, canvas.getWidth(), canvas.getHeight()),
new Line(0, canvas.getHeight(), canvas.getWidth(), 0)
};
for (Line line : lines) {
line.setStrokeWidth(30);
line.setStroke(Color.RED);
line.setFill(Color.RED);
line.setOnMouseClicked(mouseEvent -> System.out.println("!!!"));
}
canvas.drawAll(lines);
};
}
private final Consumer<VectorCanvas> drawer;
public final VectorCanvasContent content = new VectorCanvasContent();
public VectorCanvas() {
this(VectorCanvasContent.DEFAULT_DRAWER);
}
public VectorCanvas(Consumer<VectorCanvas> drawer) {
this.drawer = drawer;
getRealChildren().add(content);
draw();
}
public void clear() {
getChildren().clear();
}
public void draw() {
if (drawer != null)
drawer.accept(this);
}
public void redraw() {
clear();
draw();
}
@Override
public ObservableList<Node> getChildren() {
return content.getChildren();
}
@Override
public ObservableList<Node> getChildrenUnmodifiable() {
return content.getChildrenUnmodifiable();
}
private ObservableList<Node> getRealChildren() {
return super.getChildren();
}
private ObservableList<Node> getRealChildrenUnmodifiable() {
return super.getChildrenUnmodifiable();
}
public void draw(Shape shape) {
getChildren().add(shape);
}
public void drawAll(Shape... shapes) {
getChildren().addAll(shapes);
}
}
CodePudding user response:
You should not override getChildren()
and getChildrenUnmodifiable()
to return the children of a different node (especially a contained node).
That may confuse and break the JavaFX layout system because it would be something quite unexpected for it.