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

Shape Concepts

You can still use the Graphics methods : fillRect, fillOval, fillRoundRect, etc. In these older methods you passed in all of the coordinates as they were drawn.

In the Graphics2D approach, we define classes which implement the Shape interface first. Then we can use the shape definition multiple times: fill, draw, etc.

Also in the Shape interface model, we can specify locations more precisely than on pixel boundaries.

You can also choose to use Float or Double precision. The general pattern in java.awt.geom for these classes is:

An abstract class, and then a Double and a Float class which implement the abstract methods. So for example we have the abstract classes (note all of these implement the Shape interface):

Line2D, Rectangle2D, Ellipse2D, RoundRectangle2D, Path2D

The usable classes which extend these abstract classes are:

Line2D.Double, Rectangle2D.Double, Ellipse2D.Double, RoundRectangle2d.Double, Path2D.Double

and

Line2D.Float, Rectangle2D.Float, Ellipse2D.Float, RoundRectangle2d.Float, Path2D.Float

A class which implements the Shape interface will have the methods you can find in java.awt.Shape. A shape can be thought of as an arbitrary sequence of straight line segments or curved segments (cubic or quadratic curves are possible).

BasicShapes.java


import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.geom.RoundRectangle2D;

import javax.swing.JFrame;

public class BasicShapes extends JFrame{
    BasicShapes()
    {
        setSize(450, 220);
        setTitle("BasicShapes");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }
    public void paint(Graphics g)
    {
        Graphics2D g2d = (Graphics2D) g.create();

        RenderingHints rh = new RenderingHints(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        rh.put(RenderingHints.KEY_RENDERING,
               RenderingHints.VALUE_RENDER_QUALITY);

        g2d.setRenderingHints(rh);

        g2d.setColor(Color.black);

        g2d.fillOval(30, 50, 70, 50);
        g2d.fillRoundRect(120, 50, 70, 50, 25, 25);
        g2d.drawString("fillOval and fillRoundRect", 200, 80);

        Ellipse2D.Double ellipse = new Ellipse2D.Double(30, 120, 70, 50);
        g2d.fill(ellipse);
        RoundRectangle2D.Double roundRectangle = new RoundRectangle2D.Double(120, 120, 70, 50, 25, 25);
        g2d.fill(roundRectangle);
        g2d.drawString("fill(Shape) options", 200, 150);

        g2d.setColor(Color.red);
        g2d.drawOval(30, 50, 70, 50);

        g2d.setStroke(new BasicStroke(5));
        g2d.drawRoundRect(120, 50, 70, 50, 25, 25);

        g2d.draw(ellipse);
        g2d.draw(roundRectangle);

        g2d.dispose();
    }

    public static void main(String[] args)
    {
        BasicShapes bs1 = new BasicShapes();
    }

}






java.awt.geom.GeneralPath class

You can add any segments you wish to create a general path. Note that the segments don't have to be straight lines. The GeneralPath class provides ways for us to build complex shapes. Some of the methods found are:

- moveTo - define starting point
- lineTo - add a straight line segment
- quadTo - add a curved path which satisfies a quadratic shape
- curveTo - add a curved path which satisfies a Bezier curve (cubic shape)
- transform - apply a transformation of one shape to another (we will talk more about this later). We can rotate, scale, translate, etc. our shape.

Star_GeneralPath.java


import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.GeneralPath;

import javax.swing.JFrame;

public class Star_GeneralPath extends JFrame{
    private final double points[][] = {
            { 0, 85 }, { 75, 75 }, { 100, 10 }, { 125, 75 },
            { 200, 85 }, { 150, 125 }, { 160, 190 }, { 100, 150 },
            { 40, 190 }, { 50, 125 }, { 0, 85 }
    };
    Star_GeneralPath()
    {
        setSize(450, 220);
        setTitle("Star GeneralPath");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }
    public void paint(Graphics g)
    {
        Graphics2D g2d = (Graphics2D) g.create();

        GeneralPath star = new GeneralPath();

        star.moveTo(points[0][0], points[0][1]);  // Add the origin of the Shape

        for (int k = 1; k < points.length; k++)
            star.lineTo(points[k][0], points[k][1]); // Adding Line Segments  to the Shape

        //  star.closePath(); // doesn't seem to be needed
        g2d.fill(star);
        g2d.setColor(Color.red);
        g2d.setStroke( new BasicStroke(4));
        g2d.draw(star);

        g2d.dispose();
    }

    public static void main(String[] args)
    {
        Star_GeneralPath sgp = new Star_GeneralPath();
    }

}



Star Areas

Area class works with Shape objects. Note that an Area is a Shape. Using the Area class we combine shapes with methods like:

- add
- subtract
- intersection
- exclusiveOr



import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.RoundRectangle2D;

import javax.swing.JFrame;

public class StarAreas extends JFrame{
    private final double points[][] = {
            { 0, 85 }, { 75, 75 }, { 100, 10 }, { 125, 75 },
            { 200, 85 }, { 150, 125 }, { 160, 190 }, { 100, 150 },
            { 40, 190 }, { 50, 125 }, { 0, 85 }
    };
    StarAreas()
    {
        setSize(450, 220);
        setTitle("StarAreas");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }
    public void paint(Graphics g)
    {
        Graphics2D g2d = (Graphics2D) g.create();

        GeneralPath star = new GeneralPath();

        star.moveTo(points[0][0], points[0][1]);  // Add the origin of the Shape

        for (int k = 1; k < points.length; k++)
            star.lineTo(points[k][0], points[k][1]); // Adding Line Segments  to the Shape
        //  star.closePath(); // doesn't seem to be needed

        Ellipse2D.Double ellipse = new Ellipse2D.Double(30, 160, 70, 50);
        RoundRectangle2D.Double roundRectangle = new RoundRectangle2D.Double(150, 70, 70, 50, 25, 25);

        Area aStar = new Area(star);
        Area aEllipse = new Area(ellipse);
        Area aRoundRectangle = new Area(roundRectangle);

        aStar.add(aRoundRectangle);
        aStar.subtract(aEllipse);

        g2d.fill(aStar);
        g2d.setColor(Color.red);
        g2d.setStroke( new BasicStroke(4));
        g2d.draw(aStar);

        // Redrawing the Ellipse and RoundedRectangle in default green stroke
        // so you can see what happened better.

        g2d.setColor(Color.green);
        g2d.setStroke(new BasicStroke());
        g2d.draw(aEllipse);
        g2d.draw(aRoundRectangle);

        g2d.dispose();
    }

    public static void main(String[] args)
    {
        StarAreas sgp = new StarAreas();
    }

}



Last Updated: June 20, 2015 4:33 PM