Reputation: 485
I am developing a JavaFX desktop application and I would like to overlay a circular viewport on another panel.
Here is an very simple image depicting what I want, the white area would be transparent and showing the underlying panel. The black area would be a solid color and prevent mouse events from triggering on the underlying panel.
I have looked into using a Canvas with an event listener attached that ignores all events within the circles radius but I am wondering if there is a more efficient / less hacky method to do this?
Thanks in advance.
Upvotes: 1
Views: 2024
Reputation: 45806
Set the appropriate Shape
on the clip
property of the front Node
.
Javadoc from the clip
property:
Specifies a Node to use to define the the clipping shape for this Node. This clipping Node is not a child of this Node in the scene graph sense. Rather, it is used to define the clip for this Node.
For example, you can use an ImageView Node as a mask to represent the Clip. Or you could use one of the geometric shape Nodes such as Rectangle or Circle. Or you could use a Text node to represent the Clip.
See the class documentation for Node for scene graph structure restrictions on setting the clip. If these restrictions are violated by a change to the clip variable, the change is ignored and the previous value of the clip variable is restored.
Note that this is a conditional feature. See ConditionalFeature.SHAPE_CLIP for more information.
There is a known limitation of mixing Clip with a 3D Transform. Clipping is essentially a 2D image operation. The result of a Clip set on a Group node with 3D transformed children will cause its children to be rendered in order without Z-buffering applied between those children.
Anyway, you could to use a Rectangle
that is the same size of the Node
. Then, create a Circle
that is centered on the Rectangle
with the desired radius. From those two shapes create a new shape using Shape.subtract(rectangle, circle);
. This will create a "hole" in the middle of the Rectangle
that will show any underlying Node
.
Code example:
private void setClipViewport(Region region) {
int width = region.getWidth();
int height = region.getHeight();
Rectangle rect = new Rectangle(0, 0, width, height);
Circle circ = new Circle(width / 2, height / 2, Math.min(width, height) / 2);
Shape clip = Shape.subtract(rect, circ);
region.setClip(clip);
}
My example won't resize the clip when necessary, however. So if your UI can resize you'll need to add that behavior.
Upvotes: 4