As we mentioned with regard to the Polygon
object in the Chapter 6: Java track, Java2D follows a very object
oriented approach. You first create a 2D shape, like a rectangle
or a line, as an object. You then send the shape to the drawing
surface (i.e. the Graphics2D
context) in one operation rather than in many little incremental
draw commands. The applets below, for example, creates instances
of Shape
& Area
subclasses - rectangles and ellipses.
The diagram below shows the available shape objects, which are
defined as those that implement the java.awt.Shape
interface.
The java.awt.Shape
interface and the heirarchy of classes that implement it.
Parallelograms are abstract classes and rectangles are real
classes. As shown
only for the Line2D
class, each of the "[name]2D"
abstract classes contains
a .Float
and a .Double
real class, which can be instantiated.
We see that the Shape
interface is implemented by several classes in java.awt.geom
such as Line2D
and Rectangle2D.
Most of these classes are abstract. Concrete subclasses provide
for specifying the shape's properties as either float
or double
values. For example, Line2D.Float
and Line2D.Double
classes use constructors with float
and double
type values, respectively, to specify the beginning and ending points
of a line.
Furthermore, even drawing operations can treated as objects. For
example, When we want to perform a transformation
operation upon these 2D objects, such as a translation or rotation,
we create an instance of a transformation class that contains methods
to carry out the operation.
Drawing with Java2D in
Swing
For these demo programs we will use Swing components and draw on
a JPanel.
As we saw in the Chapter
6: Java : Drawing, to draw on a JPanel
you must override the paintComponents(Graphics
g) method. To perform Java2D graphics, you cast the
Graphics
object to its Graphics2D
subclass.
Note: For AWT components, instead
of overriding paintComponents(Graphics
g), you override the paint(Graphics
g) method.
Otherwise, the coding is the same as in
the paintComponents(Graphics
g) methods in the programs here. (Leave out, of
course, the super.paintComponent(g);
statement)
Graphics2D
is the heart of Java2D. It provides a far richer array of drawing
tools that the standard graphics context. For example, you can
give the graphics context some hints on how to render the shapes.
Here we tell it to use anti-aliasing algorithms to reduce
the jaggedness of curves and shapes.
Two shapes, an ellipse and a rectangle are created
and then each drawn with a single method call.
Note: Java2D often uses
floating-point pixel values. The rendering engine will take these
floating-point values and create a 2D array of pixels or points
for a given device, such as a monitor or printer, in a manner that
best matches these values.
Rectangle2D
is, in fact, an abstract class. The concrete sub-classes Rectangle2D.Double
& Rectangle2D.Float
take double and float arguments, respectively.
ShapesApplet.java
|
import
javax.swing.*;
import java.awt.*;
import java.awt.geom.*;// New Java2D package in Java 1.2
/** Demonstration of stroke and painting in Java2D. **/
public class ShapesApplet extends JApplet
{
public void init () {
Container content_pane = getContentPane
();
// Create an instance of ShapesPanel
ShapesPanel shapes_panel = new
ShapesPanel ();
// Add the DrawingPanel to the
content pane.
content_pane.add (shapes_panel);
} // init
} // class ShapesApplet
/** Panel on which to draw two shapes. **/
class ShapesPanel extends JPanel
{
public void paintComponent (Graphics g) {
// First paint background
super.paintComponent (g);
// The context that is passed
is actually
// the Graphics2D sub-class of
Graphics. So
// we can cast it to Graphics2D
and take advantage
// of the additional tools that
it has.
Graphics2D g2 = (Graphics2D)g;
// Options on the rendering, i.e.
the actual pixel settings
// of the drawing, can be chosen
via RenderingHints
g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// Create the two shapes, a circle
and a square.
Shape shape1 = new Ellipse2D.Double
(40.0, 60.0, 70.0, 70.);
Shape shape2 = new Rectangle2D.Double
(65.0, 35.0, 70.0, 70.0);
// Now draw the shapes.
g2.draw (shape1);
g2.draw (shape2);
} // paintComponent
} // class ShapesPanel
|
Compositing
in Java2D
Java2D gives you a lot of options when you want
to combine shapes. The compositing rules are listed on
this
page in the Sun Java2D tutorial.
We illustrate several of these compositing rules
in the next demo. Firstly, the two shapes are drawn as before
on the far left. Then a transform operation on the drawing context
shifts the origin to the right. (More about transforms
later.) Two Area
objects are derived from the two Shapes.
Area
objects can be combined to create new Area
objects.The first combination is an addition. We fill the resulting
shape with red paint and draw a blue outline. Then the translation
and combination operations are repeated for intersection, subtraction
and the exclusive OR
rules.
AreasApplet.java
This applet illustrates drawing 2 Shape
objects, then converts them to
Area
objects combined by Addition, Intersection, Subtraction
& XOR
|
import
javax.swing.*;
import java.awt.*;
import java.awt.geom.*;// New Java2D package in Java 1.2
/** Demonstration of stroke and painting in Java2D. **/
public class AreasApplet extends JApplet
{
public void init () {
Container content_pane = getContentPane
();
// Create an instance of ShapesPanel
AreasPanel areas_panel = new AreasPanel
();
// Add the DrawingPanel to the
content pane.
content_pane.add (areas_panel);
} // init
} // class AreasApplet
/** Panel on which to draw the Area objects. **/
class AreasPanel extends JPanel
{
public void paintComponent (Graphics g) {
// First paint background
super.paintComponent (g);
// The context that is passed
is actually
// the Graphics2D sub-class of
Graphics. So
// we can cast it to Graphics2D
and take advantage
// of the additional tools that
it has.
Graphics2D g2 = (Graphics2D)g;
// Options on the rendering, i.e.
the actual pixel settings
// of the drawing, can be chosen
via RenderingHints
g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// Create the two shapes, a circle
and a square.
Shape shape1 = new Ellipse2D.Double
(20.0, 45.0, 30.0, 30.);
Shape shape2 = new Rectangle2D.Double
(35.0, 35.0, 30.0, 30.0);
// Now draw the shapes.
g2.draw (shape1);
g2.draw (shape2);
// Shift the drawing origin 60
pixels to the right to make
// room for the next drawing
AffineTransform at = AffineTransform.getTranslateInstance
(60,0);
g2.transform (at);
// Now we will create Area objects
from the Shape objects.
Area area1 = new Area (shape1);
Area area2 = new Area (shape2);
// And then combine these Area
objects in several ways:
// First we simple add the Area
objects
area1.add (area2);
// In graphics2D use setPaint
instead of setColor
g2.setPaint (Color.red);
// This will fill the resulting
combined shape with blue
g2.fill (area1);
// Draw the outline of the resulting
Area.
g2.setPaint (Color.blue);
g2.draw (area1);
// Another 60 pixel shift.
g2.transform (at);
// Make another set of area objects
area1 = new Area (shape1);
area2 = new Area (shape2);
// Get the intersection of the
two Area objects and then draw it.
area1.intersect (area2);
g2.setPaint (Color.red);
g2.fill (area1);
g2.setPaint (Color.blue);
g2.draw (area1);
// Another 60 pixel shift.
g2.transform (at);
area1 = new Area (shape1);
area2 = new Area (shape2);
// Subtract area2 from area1 and
then draw the result.
area1.subtract (area2);
g2.setPaint (Color.red);
g2.fill (area1);
g2.setPaint (Color.blue);
g2.draw (area1);
// Another 60 pixel shift.
g2.transform (at);
area1 = new Area (shape1);
area2 = new Area (shape2);
// Combine with an XOR operation.
area1.exclusiveOr (area2);
g2.setPaint (Color.red);
g2.fill (area1);
g2.setPaint (Color.blue);
g2.draw (area1);
} // paintComponent
} // class AreasPanel
|
References & Web
Resources
Latest update: Oct. 3, 2005
|