多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# 剪裁 > 原文: [https://zetcode.com/gfx/java2d/clipping/](https://zetcode.com/gfx/java2d/clipping/) 在 Java 2D 教程的这一部分中,我们将讨论裁剪。 ## 剪裁 剪裁将图形限制在某个区域。 这样做是出于效率原因并产生各种效果。 使用剪裁时,我们必须使用`Graphics`对象的副本,或者恢复原始的剪裁属性。 更改剪裁不会影响现有像素; 它仅影响将来的渲染。 在以下示例中,我们将图像裁剪为圆形。 `ClippingEx.java` ```java package com.zetcode; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.Ellipse2D; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.Timer; class Surface extends JPanel implements ActionListener { private int pos_x = 8; private int pos_y = 8; private final int RADIUS = 90; private final int DELAY = 35; private Timer timer; private Image image; private final double delta[] = { 3, 3 }; public Surface() { loadImage(); determineAndSetImageSize(); initTimer(); } private void loadImage() { image = new ImageIcon("mushrooms.jpg").getImage(); } private void determineAndSetImageSize() { int h = image.getHeight(this); int w = image.getWidth(this); setPreferredSize(new Dimension(w, h)); } private void initTimer() { timer = new Timer(DELAY, this); timer.start(); } private void doDrawing(Graphics g) { Graphics2D g2d = (Graphics2D) g.create(); g2d.clip(new Ellipse2D.Double(pos_x, pos_y, RADIUS, RADIUS)); g2d.drawImage(image, 0, 0, null); g2d.dispose(); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); doDrawing(g); } @Override public void actionPerformed(ActionEvent e) { moveCircle(); repaint(); } private void moveCircle() { int w = getWidth(); int h = getHeight(); if (pos_x < 0) { delta[0] = Math.random() % 4 + 5; } else if (pos_x > w - RADIUS) { delta[0] = -(Math.random() % 4 + 5); } if (pos_y < 0 ) { delta[1] = Math.random() % 4 + 5; } else if (pos_y > h - RADIUS) { delta[1] = -(Math.random() % 4 + 5); } pos_x += delta[0]; pos_y += delta[1]; } } public class ClippingEx extends JFrame { public ClippingEx() { initUI(); } private void initUI() { setTitle("Clipping"); add(new Surface()); pack(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { ClippingEx cl = new ClippingEx(); cl.setVisible(true); } }); } } ``` 屏幕上正在移动一个圆圈,并显示了一部分基础图像。 这就像我们从孔中看一样。 ```java Graphics2D g2d = (Graphics2D) g.create(); ``` 我们创建`Graphics2D`对象的副本。 因此,更改剪裁不会影响其他在`Graphics2D`对象被重用的 Swing 零件。 ```java g2d.clip(new Ellipse2D.Double(pos_x, pos_y, RADIUS, RADIUS)); ``` `clip()`方法将现有剪裁与作为参数给出的形状结合在一起。 所得的相交设置为片段。 在我们的例子中,最终的剪裁是圆形。 ```java if (pos_x < 0) { delta[0] = Math.random() % 4 + 5; } else if (pos_x > w - RADIUS) { delta[0] = -(Math.random() % 4 + 5); } ``` 如果圆碰到窗口的左侧或右侧,则圆的移动方向会随机变化。 顶部和底部也一样。 ```java g2d.dispose(); ``` 完成绘画后,我们必须释放`Graphics2D`对象的副本。 ## 剪裁形状 在下面的示例中,我们将剪切到两个形状的交点:矩形和圆形。 `ClippingShapesEx.java` ```java package com.zetcode; import java.awt.Color; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.AffineTransform; import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.Timer; class Surface extends JPanel implements ActionListener { private Timer timer; private double rotate = 1; private int pos_x = 8; private int pos_y = 8; private final double delta[] = {1, 1}; private final int RADIUS = 60; public Surface() { initTimer(); } private void initTimer() { timer = new Timer(10, this); timer.start(); } private void doDrawing(Graphics g) { Graphics2D g2d = (Graphics2D) g; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); Shape oldClip = g2d.getClip(); int w = getWidth(); int h = getHeight(); Rectangle rect = new Rectangle(0, 0, 200, 80); AffineTransform tx = new AffineTransform(); tx.rotate(Math.toRadians(rotate), w / 2, h / 2); tx.translate(w / 2 - 100, h / 2 - 40); Ellipse2D circle = new Ellipse2D.Double(pos_x, pos_y, RADIUS, RADIUS); GeneralPath path = new GeneralPath(); path.append(tx.createTransformedShape(rect), false); g2d.clip(circle); g2d.clip(path); g2d.setPaint(new Color(110, 110, 110)); g2d.fill(circle); g2d.setClip(oldClip); g2d.draw(circle); g2d.draw(path); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); doDrawing(g); } public void step() { int w = getWidth(); int h = getHeight(); rotate += 1; if (pos_x < 0) { delta[0] = 1; } else if (pos_x > w - RADIUS) { delta[0] = -1; } if (pos_y < 0) { delta[1] = 1; } else if (pos_y > h - RADIUS) { delta[1] = -1; } pos_x += delta[0]; pos_y += delta[1]; } @Override public void actionPerformed(ActionEvent e) { step(); repaint(); } } public class ClippingShapesEx extends JFrame { public ClippingShapesEx() { initUI(); } private void initUI() { setTitle("Clipping shapes"); add(new Surface()); setSize(350, 300); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { ClippingShapesEx ex = new ClippingShapesEx(); ex.setVisible(true); } }); } } ``` 在我们的示例中,我们有一个弹跳的圆和一个旋转的矩形。 当这些形状重叠时,结果区域将充满颜色。 ```java Shape oldClip = g2d.getClip(); ``` 由于我们没有创建`Graphics2D`对象的副本,因此我们将存储旧剪裁以供以后使用。 最后,我们必须将剪裁重置为原始剪裁。 ```java Rectangle rect = new Rectangle(0, 0, 200, 80); AffineTransform tx = new AffineTransform(); tx.rotate(Math.toRadians(rotate), w / 2, h / 2); tx.translate(w / 2 - 100, h / 2 - 40); ``` 矩形正在旋转。 它始终位于面板的中间。 ```java GeneralPath path = new GeneralPath(); path.append(tx.createTransformedShape(rect), false); ``` 在这里,我们得到了旋转矩形的形状。 ```java g2d.clip(circle); g2d.clip(path); g2d.setPaint(new Color(110, 110, 110)); g2d.fill(circle); ``` 在这里,我们将绘图限制为两个形状的交点。 如果它们重叠,则结果形状的内部将充满颜色。 `clip()`方法将初始剪裁(组件的客户区域)与给定的两个形状组合在一起。 ```java g2d.setClip(oldClip); ``` 使用`setClip()`方法,我们在绘制形状之前将剪裁区域重置为旧剪裁。 与`clip()`方法不同,`setClip()`不合并剪切区域。 它将剪裁重置到新区域。 因此,此方法应专门用于还原旧剪裁。 ![Clipping shapes](https://img.kancloud.cn/e5/c9/e5c9b164123091ed5053c77d2aa7109e_350x300.jpg) 图:剪裁形状 在 Java 2D 教程的这一部分中,我们讨论了剪裁。