Title: Clipping
Course: CPS 261: Advanced Java Concepts ~ DL & MM MASTER

Clipping

You can define a shape to be used to clip your drawing. So in the example below, we have a circle that is moving around using a Timer. The circle is used as a clip area so that when we draw the whole image, only that part of the image gets drawn.

Clipping.java

penguin_family.png


import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.Timer;



public class Clipping extends JFrame implements ActionListener{

    private BufferedImage image;
    private int pos_x = 8;
    private int pos_y = 30;
    private int vx=14, vy=14;
    private final int RADIUS = 220;

    Timer timer;

    Clipping()
    {
        loadImages();
        setSize(400, 400);
        setTitle("Clipping");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);

        timer = new Timer(200, this);
        timer.setInitialDelay(500);
        timer.start();
    }
    private void loadImages() {
        try {

            image = ImageIO.read(new File("penguin_family.png"));

        } catch (IOException ex) {

            System.out.println("Error reading in images: +ex");
        }
    }
    public void paint(Graphics g)
    {
        Graphics2D g2d = (Graphics2D) g.create();
        Dimension d= getSize();
        g2d.setColor(Color.white);
        g2d.fillRect(0,0, d.width, d.height);

        g2d.clip(new Ellipse2D.Double(pos_x, pos_y, RADIUS, RADIUS));
        g2d.drawImage(image, 0, 0, null);

        g2d.dispose();

    }
    @Override
    public void actionPerformed(ActionEvent e) {

        moveCircle();
        repaint();
    }
    private int randomVelocity(){
        return (int)(14*Math.random() +14);
    }
    private void moveCircle() {

        int w = getWidth();
        int h = getHeight();

        if (pos_x < 0) {

            vx = randomVelocity();
        } else if (pos_x > w - RADIUS) {

            vx = -randomVelocity();
        }

        if (pos_y < 0 ) {

            vy = randomVelocity();
        } else if (pos_y > h - RADIUS) {

            vy = -randomVelocity();
        }

        pos_x += vx;
        pos_y += vy;
    }

    public static void main(String[] args)
    {
        Clipping clp = new Clipping();
    }


}














ClippingShapes

A lot of interesting things happening on this one.

- Our rotating rectangle is created with a transform to the center, followed by a rotation that is continuous. Note there is a Timer class to provide the continuity. Comment out one or more of these transforms to see what the rectangle does.
- Note that the 2 shapes : circle and pathRotatedRectangle are used multiple times once they are defined. This is the advantage of defining a Shape once and using it multiple times.
- Note how we saved the original clip area and restored it so we could draw normal things again. See what happens if you don't do this.
- The only attribute changed in the Graphics2D class was the clipping area. Note that because I restored the clip area to the original I technically didn't need to make a copy of the Graphics2D class and dispose it.

ClippingShapes.java


import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
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.Timer;


public class ClippingShapes extends JFrame implements ActionListener{

    private double rotate = 1;
    private int pos_x = 8;
    private int pos_y = 8;
    private int speed = 20;
    private double vx=speed, vy=speed;

    private final int RADIUS = 60;

    Timer timer;

    ClippingShapes()
    {
        setSize(400, 400);
        setTitle("ClippingShapes");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);

        timer = new Timer(200, this);
        timer.setInitialDelay(500);
        timer.start();
    }
    public void paint(Graphics g)
    {
        // Note we are not creating a Graphics2D copy
        Graphics2D g2d = (Graphics2D) g.create();
        Dimension d= getSize();
        g2d.setColor(Color.white);
        g2d.fillRect(0,0, d.width, d.height);
        g2d.setColor(Color.black);

        Ellipse2D circle = new Ellipse2D.Double(pos_x, pos_y,
                RADIUS, RADIUS);


        Shape oldClip = g2d.getClip();  // We will want to restore

        Rectangle rect = new Rectangle(0, 0, 200, 80);

        AffineTransform tx = new AffineTransform();
        // Consider commenting one or both of the following to see what happens
        tx.rotate(Math.toRadians(rotate), d.width / 2, d.height / 2);
        tx.translate(d.width / 2 - 100, d.height / 2 - 40);


        GeneralPath pathRotatedRectangle = new GeneralPath();
        pathRotatedRectangle.append(tx.createTransformedShape(rect), false);

        g2d.clip(pathRotatedRectangle);

        g2d.setPaint(Color.red);
        g2d.fill(circle);

        g2d.setClip(oldClip);


        g2d.setColor(Color.blue);
        g2d.draw(circle);
        g2d.draw(pathRotatedRectangle);

        g2d.dispose();

    }
    public void step() {

        int w = getWidth();
        int h = getHeight();

        rotate += 10;

        if (pos_x < 0) {

            vx = speed;
        } else if (pos_x > w - RADIUS) {

            vx = -speed;
        }

        if (pos_y < 0) {

            vy = speed;
        } else if (pos_y > h - RADIUS) {

            vy = -speed;
        }

        pos_x += vx;
        pos_y += vy;
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        step();
        repaint();
    }
    public static void main(String[] args)
    {
        ClippingShapes clp = new ClippingShapes();
    }


}









Last Updated: June 21, 2015 0:26 AM