How do you define a clipping region (via Graphics2D.clip(Shape)
) that has a hole in it?
for example: a Rectangle r1 minus another Rectangle r2 inside r1
I'm sure this has an easy answer, but I'm drawing a blank.
Path2D.append()
+ EVEN_ODD winding rule appear to do the trick:
package com.example.test.gui;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class HoleClipper extends JPanel
{
@Override protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
Rectangle2D r1 = getBounds();
int margin = 50;
Rectangle2D r2 = new Rectangle2D.Double(
r1.getMinX()+margin,
r1.getMinY()+margin,
r1.getWidth()-2*margin,
r1.getHeight()-2*margin);
g2d.setColor(Color.YELLOW);
g2d.fill(r1);
Path2D p = new Path2D.Double(Path2D.WIND_EVEN_ODD);
p.append(r1, false);
p.append(r2, false);
g2d.clip(p);
int spacing = 10;
g2d.setColor(Color.BLACK);
for (double d = 0; d < r1.getWidth() + r1.getHeight(); d += spacing)
{
Line2D line = new Line2D.Double(0, d, d, 0);
g2d.draw(line);
}
}
public static void main(String[] args) {
HoleClipper clipper = new HoleClipper();
clipper.setPreferredSize(new Dimension(300, 200));
JFrame frame = new JFrame("HoleClipper");
frame.setContentPane(clipper);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Looks like this is not supported by Graphics's setClip. As I read the documentation a rectangle is all that is supported:
public abstract void setClip(Shape clip)
Sets the current clipping area to an arbitrary clip shape. Not all objects that implement the Shape interface can be used to set the clip. The only Shape objects that are guaranteed to be supported are Shape objects that are obtained via the getClip method and via Rectangle objects. This method sets the user clip, which is independent of the clipping associated with device bounds and window visibility.
The GeneralPath
class is an implementation of Shape
that can represent shapes with holes in them. You define multiple path segments, one representing the "outside", and one representing the "hole". Define the clipping region you want using GeneralPath
, and then call clip()
.
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